aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Servers/HttpServer
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/Servers/HttpServer')
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs241
-rw-r--r--OpenSim/Framework/Servers/HttpServer/Interfaces/IOSHttpResponse.cs2
-rw-r--r--OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs4
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs5
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs17
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs104
6 files changed, 284 insertions, 89 deletions
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index 7f56b6f..e59d475 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,12 +544,9 @@ 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
400 Stream requestStream = req.InputStream;
401
402 string requestBody; 547 string requestBody;
403 Encoding encoding = Encoding.UTF8; 548 Encoding encoding = Encoding.UTF8;
404 using(StreamReader reader = new StreamReader(requestStream, encoding)) 549 using(StreamReader reader = new StreamReader(req.InputStream, encoding))
405 requestBody = reader.ReadToEnd(); 550 requestBody = reader.ReadToEnd();
406 551
407 Hashtable keysvals = new Hashtable(); 552 Hashtable keysvals = new Hashtable();
@@ -460,7 +605,7 @@ namespace OpenSim.Framework.Servers.HttpServer
460 } 605 }
461 606
462 OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context); 607 OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context);
463 resp.ReuseContext = true; 608// resp.ReuseContext = true;
464// resp.ReuseContext = false; 609// resp.ReuseContext = false;
465 HandleRequest(req, resp); 610 HandleRequest(req, resp);
466 611
@@ -496,6 +641,8 @@ namespace OpenSim.Framework.Servers.HttpServer
496 byte[] buffer500 = SendHTML500(response); 641 byte[] buffer500 = SendHTML500(response);
497 response.OutputStream.Write(buffer500, 0, buffer500.Length); 642 response.OutputStream.Write(buffer500, 0, buffer500.Length);
498 response.Send(); 643 response.Send();
644 if(request.InputStream.CanRead)
645 request.InputStream.Close();
499 } 646 }
500 catch 647 catch
501 { 648 {
@@ -540,7 +687,6 @@ namespace OpenSim.Framework.Servers.HttpServer
540// } 687// }
541// } 688// }
542 689
543 //response.KeepAlive = true;
544 response.SendChunked = false; 690 response.SendChunked = false;
545 691
546 string path = request.RawUrl; 692 string path = request.RawUrl;
@@ -564,11 +710,10 @@ namespace OpenSim.Framework.Servers.HttpServer
564 { 710 {
565 //m_log.Debug("[BASE HTTP SERVER]: Found Caps based HTTP Handler"); 711 //m_log.Debug("[BASE HTTP SERVER]: Found Caps based HTTP Handler");
566 IGenericHTTPHandler HTTPRequestHandler = requestHandler as IGenericHTTPHandler; 712 IGenericHTTPHandler HTTPRequestHandler = requestHandler as IGenericHTTPHandler;
567 Stream requestStream = request.InputStream;
568 713
569 string requestBody; 714 string requestBody;
570 Encoding encoding = Encoding.UTF8; 715 Encoding encoding = Encoding.UTF8;
571 using(StreamReader reader = new StreamReader(requestStream, encoding)) 716 using(StreamReader reader = new StreamReader(request.InputStream, encoding))
572 requestBody = reader.ReadToEnd(); 717 requestBody = reader.ReadToEnd();
573 718
574 Hashtable keysvals = new Hashtable(); 719 Hashtable keysvals = new Hashtable();
@@ -609,7 +754,6 @@ namespace OpenSim.Framework.Servers.HttpServer
609 else 754 else
610 { 755 {
611 IStreamHandler streamHandler = (IStreamHandler)requestHandler; 756 IStreamHandler streamHandler = (IStreamHandler)requestHandler;
612
613 using (MemoryStream memoryStream = new MemoryStream()) 757 using (MemoryStream memoryStream = new MemoryStream())
614 { 758 {
615 streamHandler.Handle(path, request.InputStream, memoryStream, request, response); 759 streamHandler.Handle(path, request.InputStream, memoryStream, request, response);
@@ -720,10 +864,6 @@ namespace OpenSim.Framework.Servers.HttpServer
720 requestEndTick = Environment.TickCount; 864 requestEndTick = Environment.TickCount;
721 865
722 response.Send(); 866 response.Send();
723
724 //response.OutputStream.Close();
725
726 //response.FreeContext();
727 } 867 }
728 catch (SocketException e) 868 catch (SocketException e)
729 { 869 {
@@ -755,6 +895,9 @@ namespace OpenSim.Framework.Servers.HttpServer
755 } 895 }
756 finally 896 finally
757 { 897 {
898 if(request.InputStream.CanRead)
899 request.InputStream.Close();
900
758 // Every month or so this will wrap and give bad numbers, not really a problem 901 // Every month or so this will wrap and give bad numbers, not really a problem
759 // since its just for reporting 902 // since its just for reporting
760 int tickdiff = requestEndTick - requestStartTick; 903 int tickdiff = requestEndTick - requestStartTick;
@@ -1008,12 +1151,13 @@ namespace OpenSim.Framework.Servers.HttpServer
1008 using (StreamReader reader = new StreamReader(requestStream, Encoding.UTF8)) 1151 using (StreamReader reader = new StreamReader(requestStream, Encoding.UTF8))
1009 requestBody = reader.ReadToEnd(); 1152 requestBody = reader.ReadToEnd();
1010 1153
1011 } 1154 }
1012 finally 1155 finally
1013 { 1156 {
1014 if (innerStream != null) 1157 if (innerStream != null && innerStream.CanRead)
1015 innerStream.Dispose(); 1158 innerStream.Dispose();
1016 requestStream.Dispose(); 1159 if (requestStream.CanRead)
1160 requestStream.Dispose();
1017 } 1161 }
1018 1162
1019 //m_log.Debug(requestBody); 1163 //m_log.Debug(requestBody);
@@ -1094,6 +1238,17 @@ namespace OpenSim.Framework.Servers.HttpServer
1094 1238
1095 if (gridproxy) 1239 if (gridproxy)
1096 xmlRprcRequest.Params.Add("gridproxy"); // Param[4] 1240 xmlRprcRequest.Params.Add("gridproxy"); // Param[4]
1241
1242 // reserve this for
1243 // ... by Fumi.Iseki for DTLNSLMoneyServer
1244 // BUT make its presence possible to detect/parse
1245 string rcn = request.IHttpClientContext.SSLCommonName;
1246 if(!string.IsNullOrWhiteSpace(rcn))
1247 {
1248 rcn = "SSLCN:" + rcn;
1249 xmlRprcRequest.Params.Add(rcn); // Param[4] or Param[5]
1250 }
1251
1097 try 1252 try
1098 { 1253 {
1099 xmlRpcResponse = method(xmlRprcRequest, request.RemoteIPEndPoint); 1254 xmlRpcResponse = method(xmlRprcRequest, request.RemoteIPEndPoint);
@@ -1265,7 +1420,6 @@ namespace OpenSim.Framework.Servers.HttpServer
1265 requestBody= reader.ReadToEnd(); 1420 requestBody= reader.ReadToEnd();
1266 1421
1267 //m_log.DebugFormat("[OGP]: {0}:{1}", request.RawUrl, requestBody); 1422 //m_log.DebugFormat("[OGP]: {0}:{1}", request.RawUrl, requestBody);
1268 response.KeepAlive = true;
1269 1423
1270 OSD llsdRequest = null; 1424 OSD llsdRequest = null;
1271 OSD llsdResponse = null; 1425 OSD llsdResponse = null;
@@ -1793,7 +1947,7 @@ namespace OpenSim.Framework.Servers.HttpServer
1793*/ 1947*/
1794 // disable this things 1948 // disable this things
1795 response.KeepAlive = false; 1949 response.KeepAlive = false;
1796 response.ReuseContext = false; 1950 // response.ReuseContext = false;
1797 1951
1798 // Cross-Origin Resource Sharing with simple requests 1952 // Cross-Origin Resource Sharing with simple requests
1799 if (responsedata.ContainsKey("access_control_allow_origin")) 1953 if (responsedata.ContainsKey("access_control_allow_origin"))
@@ -1895,7 +2049,7 @@ namespace OpenSim.Framework.Servers.HttpServer
1895 2049
1896 public void Start() 2050 public void Start()
1897 { 2051 {
1898 Start(true); 2052 Start(true,true);
1899 } 2053 }
1900 2054
1901 /// <summary> 2055 /// <summary>
@@ -1905,7 +2059,7 @@ namespace OpenSim.Framework.Servers.HttpServer
1905 /// If true then poll responses are performed asynchronsly. 2059 /// If true then poll responses are performed asynchronsly.
1906 /// Option exists to allow regression tests to perform processing synchronously. 2060 /// Option exists to allow regression tests to perform processing synchronously.
1907 /// </param> 2061 /// </param>
1908 public void Start(bool performPollResponsesAsync) 2062 public void Start(bool performPollResponsesAsync, bool runPool)
1909 { 2063 {
1910 m_log.InfoFormat( 2064 m_log.InfoFormat(
1911 "[BASE HTTP SERVER]: Starting {0} server on port {1}", UseSSL ? "HTTPS" : "HTTP", Port); 2065 "[BASE HTTP SERVER]: Starting {0} server on port {1}", UseSSL ? "HTTPS" : "HTTP", Port);
@@ -1934,6 +2088,8 @@ namespace OpenSim.Framework.Servers.HttpServer
1934 //m_httpListener.Prefixes.Add("https://+:" + (m_sslport) + "/"); 2088 //m_httpListener.Prefixes.Add("https://+:" + (m_sslport) + "/");
1935 //m_httpListener.Prefixes.Add("http://+:" + m_port + "/"); 2089 //m_httpListener.Prefixes.Add("http://+:" + m_port + "/");
1936 m_httpListener2 = CoolHTTPListener.Create(IPAddress.Any, (int)m_port, m_cert); 2090 m_httpListener2 = CoolHTTPListener.Create(IPAddress.Any, (int)m_port, m_cert);
2091 if(m_certificateValidationCallback != null)
2092 m_httpListener2.CertificateValidationCallback = m_certificateValidationCallback;
1937 m_httpListener2.ExceptionThrown += httpServerException; 2093 m_httpListener2.ExceptionThrown += httpServerException;
1938 m_httpListener2.LogWriter = httpserverlog; 2094 m_httpListener2.LogWriter = httpserverlog;
1939 } 2095 }
@@ -1943,9 +2099,11 @@ namespace OpenSim.Framework.Servers.HttpServer
1943 m_httpListener2.Start(64); 2099 m_httpListener2.Start(64);
1944 2100
1945 // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events 2101 // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events
1946 2102 if(runPool)
1947 PollServiceRequestManager = new PollServiceRequestManager(this, performPollResponsesAsync, 2, 25000); 2103 {
1948 PollServiceRequestManager.Start(); 2104 PollServiceRequestManager = new PollServiceRequestManager(this, performPollResponsesAsync, 2, 25000);
2105 PollServiceRequestManager.Start();
2106 }
1949 2107
1950 HTTPDRunning = true; 2108 HTTPDRunning = true;
1951 2109
@@ -1959,7 +2117,7 @@ namespace OpenSim.Framework.Servers.HttpServer
1959 catch (Exception e) 2117 catch (Exception e)
1960 { 2118 {
1961 m_log.Error("[BASE HTTP SERVER]: Error - " + e.Message); 2119 m_log.Error("[BASE HTTP SERVER]: Error - " + e.Message);
1962 m_log.Error("[BASE HTTP SERVER]: Tip: Do you have permission to listen on port " + m_port + ", " + m_sslport + "?"); 2120 m_log.Error("[BASE HTTP SERVER]: Tip: Do you have permission to listen on port " + m_port + "?");
1963 2121
1964 // We want this exception to halt the entire server since in current configurations we aren't too 2122 // We want this exception to halt the entire server since in current configurations we aren't too
1965 // useful without inbound HTTP. 2123 // useful without inbound HTTP.
@@ -2125,10 +2283,9 @@ namespace OpenSim.Framework.Servers.HttpServer
2125 string file = Path.Combine(".", "http_500.html"); 2283 string file = Path.Combine(".", "http_500.html");
2126 if (!File.Exists(file)) 2284 if (!File.Exists(file))
2127 return getDefaultHTTP500(); 2285 return getDefaultHTTP500();
2128 2286 string result;
2129 StreamReader sr = File.OpenText(file); 2287 using(StreamReader sr = File.OpenText(file))
2130 string result = sr.ReadToEnd(); 2288 result = sr.ReadToEnd();
2131 sr.Close();
2132 return result; 2289 return result;
2133 } 2290 }
2134 2291
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..8e1b545 100644
--- a/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs
+++ b/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs
@@ -256,7 +256,7 @@ namespace OpenSim.Framework.Servers.HttpServer
256 _httpResponse.Reason = value; 256 _httpResponse.Reason = value;
257 } 257 }
258 } 258 }
259 259/*
260 public bool ReuseContext 260 public bool ReuseContext
261 { 261 {
262 get 262 get
@@ -275,7 +275,7 @@ namespace OpenSim.Framework.Servers.HttpServer
275 } 275 }
276 } 276 }
277 } 277 }
278 278*/
279 protected IHttpResponse _httpResponse; 279 protected IHttpResponse _httpResponse;
280 private IHttpClientContext _httpClientContext; 280 private IHttpClientContext _httpClientContext;
281 281
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
index 7150aad..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,6 +45,7 @@ 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;
@@ -73,13 +75,14 @@ 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.Poll; 88 Type = EventType.Poll;
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs
index fefcb20..eb8ca0d 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)
@@ -88,7 +92,7 @@ namespace OpenSim.Framework.Servers.HttpServer
88 response.SendChunked = false; 92 response.SendChunked = false;
89 response.ContentLength64 = buffer.Length; 93 response.ContentLength64 = buffer.Length;
90 response.ContentEncoding = Encoding.UTF8; 94 response.ContentEncoding = Encoding.UTF8;
91 response.ReuseContext = false; 95// response.ReuseContext = false;
92 96
93 try 97 try
94 { 98 {
@@ -116,7 +120,7 @@ namespace OpenSim.Framework.Servers.HttpServer
116 response.SendChunked = false; 120 response.SendChunked = false;
117 response.ContentLength64 = 0; 121 response.ContentLength64 = 0;
118 response.ContentEncoding = Encoding.UTF8; 122 response.ContentEncoding = Encoding.UTF8;
119 response.ReuseContext = false; 123// response.ReuseContext = false;
120 response.KeepAlive = false; 124 response.KeepAlive = false;
121 response.SendChunked = false; 125 response.SendChunked = false;
122 response.StatusCode = 503; 126 response.StatusCode = 503;
@@ -138,8 +142,9 @@ namespace OpenSim.Framework.Servers.HttpServer
138 { 142 {
139 if (b1.contextHash != b2.contextHash) 143 if (b1.contextHash != b2.contextHash)
140 return false; 144 return false;
141 bool b = Object.ReferenceEquals(b1.HttpContext, b2.HttpContext); 145// bool b = Object.ReferenceEquals(b1.HttpContext, b2.HttpContext);
142 return b; 146// return b;
147 return true;
143 } 148 }
144 149
145 public int GetHashCode(PollServiceHttpRequest b2) 150 public int GetHashCode(PollServiceHttpRequest b2)
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
index c6a3e65..415c264 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
@@ -156,6 +156,19 @@ namespace OpenSim.Framework.Servers.HttpServer
156 } 156 }
157 } 157 }
158 158
159 public void DropByContext(PollServiceHttpRequest req)
160 {
161 Queue<PollServiceHttpRequest> ctxQeueue;
162 lock (m_bycontext)
163 {
164 if (m_bycontext.TryGetValue(req, out ctxQeueue))
165 {
166 ctxQeueue.Clear();
167 m_bycontext.Remove(req);
168 }
169 }
170 }
171
159 public void EnqueueInt(PollServiceHttpRequest req) 172 public void EnqueueInt(PollServiceHttpRequest req)
160 { 173 {
161 if (m_running) 174 if (m_running)
@@ -232,23 +245,64 @@ namespace OpenSim.Framework.Servers.HttpServer
232 { 245 {
233 PollServiceHttpRequest req = m_requests.Dequeue(4500); 246 PollServiceHttpRequest req = m_requests.Dequeue(4500);
234 Watchdog.UpdateThread(); 247 Watchdog.UpdateThread();
235 if (req != null) 248 if(req == null)
249 continue;
250
251 try
236 { 252 {
237 try 253 if(!req.HttpContext.CanSend())
254 {
255 req.PollServiceArgs.Drop(req.RequestID, req.PollServiceArgs.Id);
256 byContextDequeue(req);
257 continue;
258 }
259
260 if(req.HttpContext.IsSending())
238 { 261 {
239 if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id)) 262 if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
240 { 263 {
241 Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id); 264 req.PollServiceArgs.Drop(req.RequestID, req.PollServiceArgs.Id);
265 byContextDequeue(req);
266 }
267 else
268 ReQueueEvent(req);
269 continue;
270 }
271
272 if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id))
273 {
274 Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id);
242 275
276 m_threadPool.QueueWorkItem(x =>
277 {
278 try
279 {
280 req.DoHTTPGruntWork(m_server, responsedata);
281 }
282 catch (ObjectDisposedException) { }
283 finally
284 {
285 if(req.HttpContext.CanSend() && req.PollServiceArgs.Type == PollServiceEventArgs.EventType.Poll
286 && (Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
287 ReQueueEvent(req);
288 else
289 byContextDequeue(req);
290 }
291 return null;
292 }, null);
293 }
294 else
295 {
296 if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
297 {
243 m_threadPool.QueueWorkItem(x => 298 m_threadPool.QueueWorkItem(x =>
244 { 299 {
245 try 300 try
246 { 301 {
247 req.DoHTTPGruntWork(m_server, responsedata); 302 req.DoHTTPGruntWork(m_server,
248 } 303 req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
249 catch (ObjectDisposedException)
250 {
251 } 304 }
305 catch (ObjectDisposedException) {}
252 finally 306 finally
253 { 307 {
254 byContextDequeue(req); 308 byContextDequeue(req);
@@ -258,39 +312,15 @@ namespace OpenSim.Framework.Servers.HttpServer
258 } 312 }
259 else 313 else
260 { 314 {
261 if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms) 315 ReQueueEvent(req);
262 {
263 m_threadPool.QueueWorkItem(x =>
264 {
265 try
266 {
267 req.DoHTTPGruntWork(m_server,
268 req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
269 }
270 catch (ObjectDisposedException)
271 {
272 // Ignore it, no need to reply
273 }
274 finally
275 {
276 byContextDequeue(req);
277 }
278 return null;
279 }, null);
280 }
281 else
282 {
283 ReQueueEvent(req);
284 }
285 } 316 }
286 } 317 }
287 catch (Exception e) 318 }
288 { 319 catch (Exception e)
289 m_log.ErrorFormat("Exception in poll service thread: " + e.ToString()); 320 {
290 } 321 m_log.ErrorFormat("Exception in poll service thread: " + e.ToString());
291 } 322 }
292 } 323 }
293 } 324 }
294
295 } 325 }
296} 326}