aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Servers/BaseHttpServer.cs
diff options
context:
space:
mode:
authorTeravus Ovares2008-09-30 16:56:33 +0000
committerTeravus Ovares2008-09-30 16:56:33 +0000
commit79b2e5ac71794dd4e55228e0ac146b527fb71ddf (patch)
treec84ebcaccff670125becc16c0da17d943bfdcecb /OpenSim/Framework/Servers/BaseHttpServer.cs
parentmore concierge stuff (diff)
downloadopensim-SC_OLD-79b2e5ac71794dd4e55228e0ac146b527fb71ddf.zip
opensim-SC_OLD-79b2e5ac71794dd4e55228e0ac146b527fb71ddf.tar.gz
opensim-SC_OLD-79b2e5ac71794dd4e55228e0ac146b527fb71ddf.tar.bz2
opensim-SC_OLD-79b2e5ac71794dd4e55228e0ac146b527fb71ddf.tar.xz
* Replacing Net.HttpListener with HttpServer.
* This is a HUGE update.. and should be considered fraut with peril. * SSL Mode isn't available *yet* but I'll work on that next. * DrScofld is still working on a radical new thread pump scheme for this which will be implemented soon. * This could break the Build! This could break your Grid!
Diffstat (limited to 'OpenSim/Framework/Servers/BaseHttpServer.cs')
-rw-r--r--OpenSim/Framework/Servers/BaseHttpServer.cs272
1 files changed, 234 insertions, 38 deletions
diff --git a/OpenSim/Framework/Servers/BaseHttpServer.cs b/OpenSim/Framework/Servers/BaseHttpServer.cs
index 707f621..6090d1f 100644
--- a/OpenSim/Framework/Servers/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/BaseHttpServer.cs
@@ -40,7 +40,9 @@ using System.Xml;
40using OpenMetaverse.StructuredData; 40using OpenMetaverse.StructuredData;
41using log4net; 41using log4net;
42using Nwc.XmlRpc; 42using Nwc.XmlRpc;
43 43using CoolHTTPListener = HttpServer.HttpListener;
44using IHttpClientContext = HttpServer.IHttpClientContext;
45using IHttpRequest = HttpServer.IHttpRequest;
44 46
45namespace OpenSim.Framework.Servers 47namespace OpenSim.Framework.Servers
46{ 48{
@@ -50,6 +52,7 @@ namespace OpenSim.Framework.Servers
50 52
51 protected Thread m_workerThread; 53 protected Thread m_workerThread;
52 protected HttpListener m_httpListener; 54 protected HttpListener m_httpListener;
55 protected CoolHTTPListener m_httpListener2;
53 protected Dictionary<string, XmlRpcMethod> m_rpcHandlers = new Dictionary<string, XmlRpcMethod>(); 56 protected Dictionary<string, XmlRpcMethod> m_rpcHandlers = new Dictionary<string, XmlRpcMethod>();
54 protected DefaultLLSDMethod m_defaultLlsdHandler = null; // <-- Moving away from the monolithic.. and going to /registered/ 57 protected DefaultLLSDMethod m_defaultLlsdHandler = null; // <-- Moving away from the monolithic.. and going to /registered/
55 protected Dictionary<string, LLSDMethod> m_llsdHandlers = new Dictionary<string, LLSDMethod>(); 58 protected Dictionary<string, LLSDMethod> m_llsdHandlers = new Dictionary<string, LLSDMethod>();
@@ -102,13 +105,14 @@ namespace OpenSim.Framework.Servers
102 m_port = port; 105 m_port = port;
103 if (m_ssl) 106 if (m_ssl)
104 { 107 {
105 SetupSsl((int)sslport, CN); 108 //SetupSsl((int)sslport, CN);
106 m_sslport = sslport; 109 m_sslport = sslport;
107 } 110 }
108 } 111 }
109 112
110 113
111 114 /*
115 *
112 public bool SetupSsl(int port, string CN) 116 public bool SetupSsl(int port, string CN)
113 { 117 {
114 string searchCN = Environment.MachineName.ToUpper(); 118 string searchCN = Environment.MachineName.ToUpper();
@@ -211,7 +215,7 @@ namespace OpenSim.Framework.Servers
211 } 215 }
212 216
213 } 217 }
214 218 */
215 219
216 /// <summary> 220 /// <summary>
217 /// Add a stream handler to the http server. If the handler already exists, then nothing happens. 221 /// Add a stream handler to the http server. If the handler already exists, then nothing happens.
@@ -308,23 +312,135 @@ namespace OpenSim.Framework.Servers
308 } 312 }
309 313
310 /// <summary> 314 /// <summary>
311 /// Handle an individual http request. This method is given to a worker in the thread pool. 315 /// HttpListener Handle an individual http request. This method is given to a worker in the thread pool.
312 /// </summary> 316 /// </summary>
313 /// <param name="stateinfo"></param> 317 /// <param name="stateinfo"></param>
314 public virtual void HandleRequest(Object stateinfo) 318 public virtual void HandleRequest(Object stateinfo)
315 { 319 {
316 // force the culture to en-US 320 // force the culture to en-US
317 Culture.SetCurrentCulture(); 321
318 322
319 // If we don't catch the exception here it will just disappear into the thread pool and we'll be none the wiser 323 // If we don't catch the exception here it will just disappear into the thread pool and we'll be none the wiser
320 try 324 try
321 { 325 {
322 HttpListenerContext context = (HttpListenerContext) stateinfo; 326 HttpListenerContext context = (HttpListenerContext)stateinfo;
323 327
324 OSHttpRequest request = new OSHttpRequest(context.Request); 328 OSHttpRequest request = new OSHttpRequest(context.Request);
325 OSHttpResponse response = new OSHttpResponse(context.Response); 329 OSHttpResponse response = new OSHttpResponse(context.Response);
326 context.Response.ProtocolVersion = new Version("1.0"); 330
327 context.Response.KeepAlive = false; 331 HandleRequest(request, response);
332
333 }
334 catch (SocketException e)
335 {
336 // At least on linux, it appears that if the client makes a request without requiring the response,
337 // an unconnected socket exception is thrown when we close the response output stream. There's no
338 // obvious way to tell if the client didn't require the response, so instead we'll catch and ignore
339 // the exception instead.
340 //
341 // An alternative may be to turn off all response write exceptions on the HttpListener, but let's go
342 // with the minimum first
343 m_log.WarnFormat("[BASE HTTP SERVER]: HandleRequest threw {0}.\nNOTE: this may be spurious on Linux", e);
344 }
345 catch (Exception e)
346 {
347 m_log.ErrorFormat("[BASE HTTP SERVER]: HandleRequest() threw {0}", e);
348 }
349 }
350
351 /*
352 /// <summary>
353 /// HttpListener Handle an individual http request. This method is given to a worker in the thread pool.
354 /// </summary>
355 /// <param name="stateinfo"></param>
356 public virtual void HandleRequestHttpServer(Object stateinfo)
357 {
358 // force the culture to en-US
359
360
361 // If we don't catch the exception here it will just disappear into the thread pool and we'll be none the wiser
362 try
363 {
364 HttpServerContextObj context = (HttpServerContextObj)stateinfo;
365
366 OSHttpRequest request = new OSHttpRequest(context.Request);
367 OSHttpResponse response = new OSHttpResponse(context.Response);
368
369 HandleRequest(request, response);
370
371 }
372 catch (SocketException e)
373 {
374 // At least on linux, it appears that if the client makes a request without requiring the response,
375 // an unconnected socket exception is thrown when we close the response output stream. There's no
376 // obvious way to tell if the client didn't require the response, so instead we'll catch and ignore
377 // the exception instead.
378 //
379 // An alternative may be to turn off all response write exceptions on the HttpListener, but let's go
380 // with the minimum first
381 m_log.WarnFormat("[BASE HTTP SERVER]: HandleRequest threw {0}.\nNOTE: this may be spurious on Linux", e);
382 }
383 catch (Exception e)
384 {
385 m_log.ErrorFormat("[BASE HTTP SERVER]: HandleRequest() threw {0}", e);
386 }
387 }
388 */
389 public void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request)
390 {
391 OSHttpRequest req = new OSHttpRequest(context, request);
392 OSHttpResponse resp = new OSHttpResponse(new HttpServer.HttpResponse(context, request));
393
394 //HttpServerContextObj objstate= new HttpServerContextObj(req,resp);
395 //ThreadPool.QueueUserWorkItem(new WaitCallback(ConvertIHttpClientContextToOSHttp), (object)objstate);
396 HandleRequest(req, resp);
397 }
398
399 public void ConvertIHttpClientContextToOSHttp(object stateinfo)
400 {
401 HttpServerContextObj objstate = (HttpServerContextObj)stateinfo;
402 //OSHttpRequest request = new OSHttpRequest(objstate.context,objstate.req);
403 //OSHttpResponse resp = new OSHttpResponse(new HttpServer.HttpResponse(objstate.context, objstate.req));
404
405 OSHttpRequest request = objstate.oreq;
406 OSHttpResponse resp = objstate.oresp;
407 //OSHttpResponse resp = new OSHttpResponse(new HttpServer.HttpResponse(objstate.context, objstate.req));
408
409 /*
410 request.AcceptTypes = objstate.req.AcceptTypes;
411 request.ContentLength = (long)objstate.req.ContentLength;
412 request.Headers = objstate.req.Headers;
413 request.HttpMethod = objstate.req.Method;
414 request.InputStream = objstate.req.Body;
415 foreach (string str in request.Headers)
416 {
417 if (str.ToLower().Contains("content-type: "))
418 {
419 request.ContentType = str.Substring(13, str.Length - 13);
420 break;
421 }
422 }
423 //request.KeepAlive = objstate.req.
424 foreach (HttpServer.HttpInput httpinput in objstate.req.QueryString)
425 {
426 request.QueryString.Add(httpinput.Name, httpinput[httpinput.Name]);
427 }
428
429 //request.Query = objstate.req.//objstate.req.QueryString;
430 //foreach (
431 //request.QueryString = objstate.req.QueryString;
432
433 */
434 HandleRequest(request,resp);
435
436
437 }
438
439 public virtual void HandleRequest(OSHttpRequest request, OSHttpResponse response)
440 {
441 try
442 {
443 Culture.SetCurrentCulture();
328 // This is the REST agent interface. We require an agent to properly identify 444 // This is the REST agent interface. We require an agent to properly identify
329 // itself. If the REST handler recognizes the prefix it will attempt to 445 // itself. If the REST handler recognizes the prefix it will attempt to
330 // satisfy the request. If it is not recognizable, and no damage has occurred 446 // satisfy the request. If it is not recognizable, and no damage has occurred
@@ -431,12 +547,22 @@ namespace OpenSim.Framework.Servers
431 try 547 try
432 { 548 {
433 response.OutputStream.Write(buffer, 0, buffer.Length); 549 response.OutputStream.Write(buffer, 0, buffer.Length);
434 response.OutputStream.Close(); 550 //response.OutputStream.Close();
435 } 551 }
436 catch (HttpListenerException) 552 catch (HttpListenerException)
437 { 553 {
438 m_log.WarnFormat("[BASE HTTP SERVER]: HTTP request abnormally terminated."); 554 m_log.WarnFormat("[BASE HTTP SERVER]: HTTP request abnormally terminated.");
439 } 555 }
556 //response.OutputStream.Close();
557 try
558 {
559 response.Send();
560 }
561 catch (SocketException e)
562 {
563 // This has to be here to prevent a Linux/Mono crash
564 m_log.WarnFormat("[BASE HTTP SERVER] XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
565 }
440 return; 566 return;
441 } 567 }
442 568
@@ -489,7 +615,7 @@ namespace OpenSim.Framework.Servers
489 // with the minimum first 615 // with the minimum first
490 m_log.WarnFormat("[BASE HTTP SERVER]: HandleRequest threw {0}.\nNOTE: this may be spurious on Linux", e); 616 m_log.WarnFormat("[BASE HTTP SERVER]: HandleRequest threw {0}.\nNOTE: this may be spurious on Linux", e);
491 } 617 }
492 catch (Exception e) 618 catch (EndOfStreamException e)
493 { 619 {
494 m_log.ErrorFormat("[BASE HTTP SERVER]: HandleRequest() threw {0}", e); 620 m_log.ErrorFormat("[BASE HTTP SERVER]: HandleRequest() threw {0}", e);
495 } 621 }
@@ -739,7 +865,16 @@ namespace OpenSim.Framework.Servers
739 } 865 }
740 finally 866 finally
741 { 867 {
742 response.OutputStream.Close(); 868 //response.OutputStream.Close();
869 try
870 {
871 response.Send();
872 }
873 catch (SocketException e)
874 {
875 // This has to be here to prevent a Linux/Mono crash
876 m_log.WarnFormat("[BASE HTTP SERVER] XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
877 }
743 } 878 }
744 } 879 }
745 880
@@ -883,7 +1018,16 @@ namespace OpenSim.Framework.Servers
883 response.SendChunked = false; 1018 response.SendChunked = false;
884 response.KeepAlive = false; 1019 response.KeepAlive = false;
885 response.StatusCode = (int)OSHttpStatusCode.ServerErrorInternalError; 1020 response.StatusCode = (int)OSHttpStatusCode.ServerErrorInternalError;
886 response.OutputStream.Close(); 1021 //response.OutputStream.Close();
1022 try
1023 {
1024 response.Send();
1025 }
1026 catch (SocketException f)
1027 {
1028 // This has to be here to prevent a Linux/Mono crash
1029 m_log.WarnFormat("[BASE HTTP SERVER] XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", f);
1030 }
887 } 1031 }
888 catch(Exception) 1032 catch(Exception)
889 { 1033 {
@@ -996,6 +1140,10 @@ namespace OpenSim.Framework.Servers
996 { 1140 {
997 response.StatusDescription = (string)responsedata["error_status_text"]; 1141 response.StatusDescription = (string)responsedata["error_status_text"];
998 } 1142 }
1143 if (responsedata.ContainsKey("http_protocol_version"))
1144 {
1145 response.ProtocolVersion = (string)responsedata["http_protocol_version"];
1146 }
999 1147
1000 if (responsedata.ContainsKey("keepalive")) 1148 if (responsedata.ContainsKey("keepalive"))
1001 { 1149 {
@@ -1049,7 +1197,16 @@ namespace OpenSim.Framework.Servers
1049 } 1197 }
1050 finally 1198 finally
1051 { 1199 {
1052 response.OutputStream.Close(); 1200 //response.OutputStream.Close();
1201 try
1202 {
1203 response.Send();
1204 }
1205 catch (SocketException e)
1206 {
1207 // This has to be here to prevent a Linux/Mono crash
1208 m_log.WarnFormat("[BASE HTTP SERVER] XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
1209 }
1053 } 1210 }
1054 1211
1055 } 1212 }
@@ -1077,7 +1234,16 @@ namespace OpenSim.Framework.Servers
1077 } 1234 }
1078 finally 1235 finally
1079 { 1236 {
1080 response.OutputStream.Close(); 1237 //response.OutputStream.Close();
1238 try
1239 {
1240 response.Send();
1241 }
1242 catch (SocketException e)
1243 {
1244 // This has to be here to prevent a Linux/Mono crash
1245 m_log.WarnFormat("[BASE HTTP SERVER] XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
1246 }
1081 } 1247 }
1082 } 1248 }
1083 1249
@@ -1103,7 +1269,16 @@ namespace OpenSim.Framework.Servers
1103 } 1269 }
1104 finally 1270 finally
1105 { 1271 {
1106 response.OutputStream.Close(); 1272 //response.OutputStream.Close();
1273 try
1274 {
1275 response.Send();
1276 }
1277 catch (SocketException e)
1278 {
1279 // This has to be here to prevent a Linux/Mono crash
1280 m_log.WarnFormat("[BASE HTTP SERVER] XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
1281 }
1107 } 1282 }
1108 } 1283 }
1109 1284
@@ -1111,11 +1286,12 @@ namespace OpenSim.Framework.Servers
1111 { 1286 {
1112 m_log.Info("[HTTPD]: Starting up HTTP Server"); 1287 m_log.Info("[HTTPD]: Starting up HTTP Server");
1113 1288
1114 m_workerThread = new Thread(new ThreadStart(StartHTTP)); 1289 //m_workerThread = new Thread(new ThreadStart(StartHTTP));
1115 m_workerThread.Name = "HttpThread"; 1290 //m_workerThread.Name = "HttpThread";
1116 m_workerThread.IsBackground = true; 1291 //m_workerThread.IsBackground = true;
1117 m_workerThread.Start(); 1292 //m_workerThread.Start();
1118 ThreadTracker.Add(m_workerThread); 1293 //ThreadTracker.Add(m_workerThread);
1294 StartHTTP();
1119 } 1295 }
1120 1296
1121 private void StartHTTP() 1297 private void StartHTTP()
@@ -1123,31 +1299,30 @@ namespace OpenSim.Framework.Servers
1123 try 1299 try
1124 { 1300 {
1125 m_log.Info("[HTTPD]: Spawned main thread OK"); 1301 m_log.Info("[HTTPD]: Spawned main thread OK");
1126 m_httpListener = new HttpListener(); 1302 //m_httpListener = new HttpListener();
1127 1303
1128 if (!m_ssl) 1304 if (!m_ssl)
1129 { 1305 {
1130 m_httpListener.Prefixes.Add("http://+:" + m_port + "/"); 1306 //m_httpListener.Prefixes.Add("http://+:" + m_port + "/");
1131 //m_httpListener.Prefixes.Add("http://10.1.1.5:" + m_port + "/"); 1307 //m_httpListener.Prefixes.Add("http://10.1.1.5:" + m_port + "/");
1308 m_httpListener2 = new HttpServer.HttpListener(IPAddress.Any, (int)m_port);
1132 } 1309 }
1133 else 1310 else
1134 { 1311 {
1135 m_httpListener.Prefixes.Add("https://+:" + (m_sslport) + "/"); 1312 //m_httpListener.Prefixes.Add("https://+:" + (m_sslport) + "/");
1136 m_httpListener.Prefixes.Add("http://+:" + m_port + "/"); 1313 //m_httpListener.Prefixes.Add("http://+:" + m_port + "/");
1137 } 1314 }
1138 HttpListenerPrefixCollection prefixs = m_httpListener.Prefixes;
1139 1315
1140 foreach (string prefix in prefixs) 1316 m_httpListener2.RequestHandler += OnHandleRequestIOThread;
1141 System.Console.WriteLine("Listening on: " + prefix); 1317 //m_httpListener.Start();
1142 1318 m_httpListener2.Start(5);
1143 m_httpListener.Start();
1144 1319
1145 HttpListenerContext context; 1320 //HttpListenerContext context;
1146 while (true) 1321 //while (true)
1147 { 1322 //{
1148 context = m_httpListener.GetContext(); 1323 // context = m_httpListener.GetContext();
1149 ThreadPool.QueueUserWorkItem(new WaitCallback(HandleRequest), context); 1324 // ThreadPool.QueueUserWorkItem(new WaitCallback(HandleRequest), context);
1150 } 1325 // }
1151 } 1326 }
1152 catch (Exception e) 1327 catch (Exception e)
1153 { 1328 {
@@ -1244,4 +1419,25 @@ namespace OpenSim.Framework.Servers
1244 return "<HTML><HEAD><TITLE>500 Internal Server Error</TITLE><BODY><BR /><H1>Ooops!</H1><P>The server you requested is overun by knomes! Find hippos quick!</P></BODY></HTML>"; 1419 return "<HTML><HEAD><TITLE>500 Internal Server Error</TITLE><BODY><BR /><H1>Ooops!</H1><P>The server you requested is overun by knomes! Find hippos quick!</P></BODY></HTML>";
1245 } 1420 }
1246 } 1421 }
1422
1423 public class HttpServerContextObj
1424 {
1425 public IHttpClientContext context = null;
1426 public IHttpRequest req = null;
1427 public OSHttpRequest oreq = null;
1428 public OSHttpResponse oresp = null;
1429
1430 public HttpServerContextObj(IHttpClientContext contxt, IHttpRequest reqs)
1431 {
1432 context = contxt;
1433 req = reqs;
1434 }
1435
1436 public HttpServerContextObj(OSHttpRequest osreq, OSHttpResponse osresp)
1437 {
1438 oreq = osreq;
1439 oresp = osresp;
1440 }
1441
1442 }
1247} 1443}