diff options
Diffstat (limited to 'OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs')
-rw-r--r-- | OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs | 274 |
1 files changed, 176 insertions, 98 deletions
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 788a0b9..3198891 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs | |||
@@ -54,8 +54,23 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
54 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 54 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
55 | private HttpServerLogWriter httpserverlog = new HttpServerLogWriter(); | 55 | private HttpServerLogWriter httpserverlog = new HttpServerLogWriter(); |
56 | 56 | ||
57 | /// <summary> | ||
58 | /// Gets or sets the debug level. | ||
59 | /// </summary> | ||
60 | /// <value> | ||
61 | /// See MainServer.DebugLevel. | ||
62 | /// </value> | ||
57 | public int DebugLevel { get; set; } | 63 | public int DebugLevel { get; set; } |
58 | 64 | ||
65 | /// <summary> | ||
66 | /// Request number for diagnostic purposes. | ||
67 | /// </summary> | ||
68 | /// <remarks> | ||
69 | /// This is an internal number. In some debug situations an external number may also be supplied in the | ||
70 | /// opensim-request-id header but we are not currently logging this. | ||
71 | /// </remarks> | ||
72 | public int RequestNumber { get; private set; } | ||
73 | |||
59 | private volatile int NotSocketErrors = 0; | 74 | private volatile int NotSocketErrors = 0; |
60 | public volatile bool HTTPDRunning = false; | 75 | public volatile bool HTTPDRunning = false; |
61 | 76 | ||
@@ -67,7 +82,7 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
67 | protected Dictionary<string, LLSDMethod> m_llsdHandlers = new Dictionary<string, LLSDMethod>(); | 82 | protected Dictionary<string, LLSDMethod> m_llsdHandlers = new Dictionary<string, LLSDMethod>(); |
68 | protected Dictionary<string, IRequestHandler> m_streamHandlers = new Dictionary<string, IRequestHandler>(); | 83 | protected Dictionary<string, IRequestHandler> m_streamHandlers = new Dictionary<string, IRequestHandler>(); |
69 | protected Dictionary<string, GenericHTTPMethod> m_HTTPHandlers = new Dictionary<string, GenericHTTPMethod>(); | 84 | protected Dictionary<string, GenericHTTPMethod> m_HTTPHandlers = new Dictionary<string, GenericHTTPMethod>(); |
70 | protected Dictionary<string, IHttpAgentHandler> m_agentHandlers = new Dictionary<string, IHttpAgentHandler>(); | 85 | // protected Dictionary<string, IHttpAgentHandler> m_agentHandlers = new Dictionary<string, IHttpAgentHandler>(); |
71 | protected Dictionary<string, PollServiceEventArgs> m_pollHandlers = | 86 | protected Dictionary<string, PollServiceEventArgs> m_pollHandlers = |
72 | new Dictionary<string, PollServiceEventArgs>(); | 87 | new Dictionary<string, PollServiceEventArgs>(); |
73 | 88 | ||
@@ -245,29 +260,29 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
245 | return new List<string>(m_pollHandlers.Keys); | 260 | return new List<string>(m_pollHandlers.Keys); |
246 | } | 261 | } |
247 | 262 | ||
248 | // Note that the agent string is provided simply to differentiate | 263 | // // Note that the agent string is provided simply to differentiate |
249 | // the handlers - it is NOT required to be an actual agent header | 264 | // // the handlers - it is NOT required to be an actual agent header |
250 | // value. | 265 | // // value. |
251 | public bool AddAgentHandler(string agent, IHttpAgentHandler handler) | 266 | // public bool AddAgentHandler(string agent, IHttpAgentHandler handler) |
252 | { | 267 | // { |
253 | lock (m_agentHandlers) | 268 | // lock (m_agentHandlers) |
254 | { | 269 | // { |
255 | if (!m_agentHandlers.ContainsKey(agent)) | 270 | // if (!m_agentHandlers.ContainsKey(agent)) |
256 | { | 271 | // { |
257 | m_agentHandlers.Add(agent, handler); | 272 | // m_agentHandlers.Add(agent, handler); |
258 | return true; | 273 | // return true; |
259 | } | 274 | // } |
260 | } | 275 | // } |
261 | 276 | // | |
262 | //must already have a handler for that path so return false | 277 | // //must already have a handler for that path so return false |
263 | return false; | 278 | // return false; |
264 | } | 279 | // } |
265 | 280 | // | |
266 | public List<string> GetAgentHandlerKeys() | 281 | // public List<string> GetAgentHandlerKeys() |
267 | { | 282 | // { |
268 | lock (m_agentHandlers) | 283 | // lock (m_agentHandlers) |
269 | return new List<string>(m_agentHandlers.Keys); | 284 | // return new List<string>(m_agentHandlers.Keys); |
270 | } | 285 | // } |
271 | 286 | ||
272 | public bool AddLLSDHandler(string path, LLSDMethod handler) | 287 | public bool AddLLSDHandler(string path, LLSDMethod handler) |
273 | { | 288 | { |
@@ -296,6 +311,8 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
296 | 311 | ||
297 | private void OnRequest(object source, RequestEventArgs args) | 312 | private void OnRequest(object source, RequestEventArgs args) |
298 | { | 313 | { |
314 | RequestNumber++; | ||
315 | |||
299 | try | 316 | try |
300 | { | 317 | { |
301 | IHttpClientContext context = (IHttpClientContext)source; | 318 | IHttpClientContext context = (IHttpClientContext)source; |
@@ -406,7 +423,6 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
406 | string requestMethod = request.HttpMethod; | 423 | string requestMethod = request.HttpMethod; |
407 | string uriString = request.RawUrl; | 424 | string uriString = request.RawUrl; |
408 | 425 | ||
409 | // string reqnum = "unknown"; | ||
410 | int requestStartTick = Environment.TickCount; | 426 | int requestStartTick = Environment.TickCount; |
411 | 427 | ||
412 | // Will be adjusted later on. | 428 | // Will be adjusted later on. |
@@ -423,22 +439,22 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
423 | 439 | ||
424 | Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true); | 440 | Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true); |
425 | 441 | ||
426 | // This is the REST agent interface. We require an agent to properly identify | 442 | // // This is the REST agent interface. We require an agent to properly identify |
427 | // itself. If the REST handler recognizes the prefix it will attempt to | 443 | // // itself. If the REST handler recognizes the prefix it will attempt to |
428 | // satisfy the request. If it is not recognizable, and no damage has occurred | 444 | // // satisfy the request. If it is not recognizable, and no damage has occurred |
429 | // the request can be passed through to the other handlers. This is a low | 445 | // // the request can be passed through to the other handlers. This is a low |
430 | // probability event; if a request is matched it is normally expected to be | 446 | // // probability event; if a request is matched it is normally expected to be |
431 | // handled | 447 | // // handled |
432 | IHttpAgentHandler agentHandler; | 448 | // IHttpAgentHandler agentHandler; |
433 | 449 | // | |
434 | if (TryGetAgentHandler(request, response, out agentHandler)) | 450 | // if (TryGetAgentHandler(request, response, out agentHandler)) |
435 | { | 451 | // { |
436 | if (HandleAgentRequest(agentHandler, request, response)) | 452 | // if (HandleAgentRequest(agentHandler, request, response)) |
437 | { | 453 | // { |
438 | requestEndTick = Environment.TickCount; | 454 | // requestEndTick = Environment.TickCount; |
439 | return; | 455 | // return; |
440 | } | 456 | // } |
441 | } | 457 | // } |
442 | 458 | ||
443 | //response.KeepAlive = true; | 459 | //response.KeepAlive = true; |
444 | response.SendChunked = false; | 460 | response.SendChunked = false; |
@@ -450,9 +466,7 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
450 | if (TryGetStreamHandler(handlerKey, out requestHandler)) | 466 | if (TryGetStreamHandler(handlerKey, out requestHandler)) |
451 | { | 467 | { |
452 | if (DebugLevel >= 3) | 468 | if (DebugLevel >= 3) |
453 | m_log.DebugFormat( | 469 | LogIncomingToStreamHandler(request, requestHandler); |
454 | "[BASE HTTP SERVER]: Found stream handler for {0} {1} {2} {3}", | ||
455 | request.HttpMethod, request.Url.PathAndQuery, requestHandler.Name, requestHandler.Description); | ||
456 | 470 | ||
457 | response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type. | 471 | response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type. |
458 | 472 | ||
@@ -529,11 +543,8 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
529 | { | 543 | { |
530 | case null: | 544 | case null: |
531 | case "text/html": | 545 | case "text/html": |
532 | |||
533 | if (DebugLevel >= 3) | 546 | if (DebugLevel >= 3) |
534 | m_log.DebugFormat( | 547 | LogIncomingToContentTypeHandler(request); |
535 | "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}", | ||
536 | request.ContentType, request.HttpMethod, request.Url.PathAndQuery); | ||
537 | 548 | ||
538 | buffer = HandleHTTPRequest(request, response); | 549 | buffer = HandleHTTPRequest(request, response); |
539 | break; | 550 | break; |
@@ -541,11 +552,8 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
541 | case "application/llsd+xml": | 552 | case "application/llsd+xml": |
542 | case "application/xml+llsd": | 553 | case "application/xml+llsd": |
543 | case "application/llsd+json": | 554 | case "application/llsd+json": |
544 | |||
545 | if (DebugLevel >= 3) | 555 | if (DebugLevel >= 3) |
546 | m_log.DebugFormat( | 556 | LogIncomingToContentTypeHandler(request); |
547 | "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}", | ||
548 | request.ContentType, request.HttpMethod, request.Url.PathAndQuery); | ||
549 | 557 | ||
550 | buffer = HandleLLSDRequests(request, response); | 558 | buffer = HandleLLSDRequests(request, response); |
551 | break; | 559 | break; |
@@ -564,9 +572,7 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
564 | if (DoWeHaveALLSDHandler(request.RawUrl)) | 572 | if (DoWeHaveALLSDHandler(request.RawUrl)) |
565 | { | 573 | { |
566 | if (DebugLevel >= 3) | 574 | if (DebugLevel >= 3) |
567 | m_log.DebugFormat( | 575 | LogIncomingToContentTypeHandler(request); |
568 | "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}", | ||
569 | request.ContentType, request.HttpMethod, request.Url.PathAndQuery); | ||
570 | 576 | ||
571 | buffer = HandleLLSDRequests(request, response); | 577 | buffer = HandleLLSDRequests(request, response); |
572 | } | 578 | } |
@@ -574,18 +580,14 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
574 | else if (DoWeHaveAHTTPHandler(request.RawUrl)) | 580 | else if (DoWeHaveAHTTPHandler(request.RawUrl)) |
575 | { | 581 | { |
576 | if (DebugLevel >= 3) | 582 | if (DebugLevel >= 3) |
577 | m_log.DebugFormat( | 583 | LogIncomingToContentTypeHandler(request); |
578 | "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}", | ||
579 | request.ContentType, request.HttpMethod, request.Url.PathAndQuery); | ||
580 | 584 | ||
581 | buffer = HandleHTTPRequest(request, response); | 585 | buffer = HandleHTTPRequest(request, response); |
582 | } | 586 | } |
583 | else | 587 | else |
584 | { | 588 | { |
585 | if (DebugLevel >= 3) | 589 | if (DebugLevel >= 3) |
586 | m_log.DebugFormat( | 590 | LogIncomingToXmlRpcHandler(request); |
587 | "[BASE HTTP SERVER]: Assuming a generic XMLRPC request for {0} {1}", | ||
588 | request.HttpMethod, request.Url.PathAndQuery); | ||
589 | 591 | ||
590 | // generic login request. | 592 | // generic login request. |
591 | buffer = HandleXmlRpcRequests(request, response); | 593 | buffer = HandleXmlRpcRequests(request, response); |
@@ -629,11 +631,11 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
629 | } | 631 | } |
630 | catch (IOException e) | 632 | catch (IOException e) |
631 | { | 633 | { |
632 | m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.Message), e); | 634 | m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.StackTrace), e); |
633 | } | 635 | } |
634 | catch (Exception e) | 636 | catch (Exception e) |
635 | { | 637 | { |
636 | m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.Message), e); | 638 | m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.StackTrace), e); |
637 | SendHTML500(response); | 639 | SendHTML500(response); |
638 | } | 640 | } |
639 | finally | 641 | finally |
@@ -644,17 +646,93 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
644 | if (tickdiff > 3000 && (requestHandler == null || requestHandler.Name == null || requestHandler.Name != "GetTexture")) | 646 | if (tickdiff > 3000 && (requestHandler == null || requestHandler.Name == null || requestHandler.Name != "GetTexture")) |
645 | { | 647 | { |
646 | m_log.InfoFormat( | 648 | m_log.InfoFormat( |
647 | "[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} from {4} took {5}ms", | 649 | "[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms", |
650 | RequestNumber, | ||
648 | requestMethod, | 651 | requestMethod, |
649 | uriString, | 652 | uriString, |
650 | requestHandler != null ? requestHandler.Name : "", | 653 | requestHandler != null ? requestHandler.Name : "", |
651 | requestHandler != null ? requestHandler.Description : "", | 654 | requestHandler != null ? requestHandler.Description : "", |
652 | request.RemoteIPEndPoint.ToString(), | 655 | request.RemoteIPEndPoint, |
656 | tickdiff); | ||
657 | } | ||
658 | else if (DebugLevel >= 4) | ||
659 | { | ||
660 | m_log.DebugFormat( | ||
661 | "[BASE HTTP SERVER]: HTTP IN {0} :{1} took {2}ms", | ||
662 | RequestNumber, | ||
663 | Port, | ||
653 | tickdiff); | 664 | tickdiff); |
654 | } | 665 | } |
655 | } | 666 | } |
656 | } | 667 | } |
657 | 668 | ||
669 | private void LogIncomingToStreamHandler(OSHttpRequest request, IRequestHandler requestHandler) | ||
670 | { | ||
671 | m_log.DebugFormat( | ||
672 | "[BASE HTTP SERVER]: HTTP IN {0} :{1} stream handler {2} {3} {4} {5} from {6}", | ||
673 | RequestNumber, | ||
674 | Port, | ||
675 | request.HttpMethod, | ||
676 | request.Url.PathAndQuery, | ||
677 | requestHandler.Name, | ||
678 | requestHandler.Description, | ||
679 | request.RemoteIPEndPoint); | ||
680 | |||
681 | if (DebugLevel >= 5) | ||
682 | LogIncomingInDetail(request); | ||
683 | } | ||
684 | |||
685 | private void LogIncomingToContentTypeHandler(OSHttpRequest request) | ||
686 | { | ||
687 | m_log.DebugFormat( | ||
688 | "[BASE HTTP SERVER]: HTTP IN {0} :{1} {2} content type handler {3} {4} from {5}", | ||
689 | RequestNumber, | ||
690 | Port, | ||
691 | (request.ContentType == null || request.ContentType == "") ? "not set" : request.ContentType, | ||
692 | request.HttpMethod, | ||
693 | request.Url.PathAndQuery, | ||
694 | request.RemoteIPEndPoint); | ||
695 | |||
696 | if (DebugLevel >= 5) | ||
697 | LogIncomingInDetail(request); | ||
698 | } | ||
699 | |||
700 | private void LogIncomingToXmlRpcHandler(OSHttpRequest request) | ||
701 | { | ||
702 | m_log.DebugFormat( | ||
703 | "[BASE HTTP SERVER]: HTTP IN {0} :{1} assumed generic XMLRPC request {2} {3} from {4}", | ||
704 | RequestNumber, | ||
705 | Port, | ||
706 | request.HttpMethod, | ||
707 | request.Url.PathAndQuery, | ||
708 | request.RemoteIPEndPoint); | ||
709 | |||
710 | if (DebugLevel >= 5) | ||
711 | LogIncomingInDetail(request); | ||
712 | } | ||
713 | |||
714 | private void LogIncomingInDetail(OSHttpRequest request) | ||
715 | { | ||
716 | using (StreamReader reader = new StreamReader(Util.Copy(request.InputStream), Encoding.UTF8)) | ||
717 | { | ||
718 | string output; | ||
719 | |||
720 | if (DebugLevel == 5) | ||
721 | { | ||
722 | const int sampleLength = 80; | ||
723 | char[] sampleChars = new char[sampleLength]; | ||
724 | reader.Read(sampleChars, 0, sampleLength); | ||
725 | output = new string(sampleChars); | ||
726 | } | ||
727 | else | ||
728 | { | ||
729 | output = reader.ReadToEnd(); | ||
730 | } | ||
731 | |||
732 | m_log.DebugFormat("[BASE HTTP SERVER]: {0}...", output.Replace("\n", @"\n")); | ||
733 | } | ||
734 | } | ||
735 | |||
658 | private bool TryGetStreamHandler(string handlerKey, out IRequestHandler streamHandler) | 736 | private bool TryGetStreamHandler(string handlerKey, out IRequestHandler streamHandler) |
659 | { | 737 | { |
660 | string bestMatch = null; | 738 | string bestMatch = null; |
@@ -747,24 +825,24 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
747 | } | 825 | } |
748 | } | 826 | } |
749 | 827 | ||
750 | private bool TryGetAgentHandler(OSHttpRequest request, OSHttpResponse response, out IHttpAgentHandler agentHandler) | 828 | // private bool TryGetAgentHandler(OSHttpRequest request, OSHttpResponse response, out IHttpAgentHandler agentHandler) |
751 | { | 829 | // { |
752 | agentHandler = null; | 830 | // agentHandler = null; |
753 | 831 | // | |
754 | lock (m_agentHandlers) | 832 | // lock (m_agentHandlers) |
755 | { | 833 | // { |
756 | foreach (IHttpAgentHandler handler in m_agentHandlers.Values) | 834 | // foreach (IHttpAgentHandler handler in m_agentHandlers.Values) |
757 | { | 835 | // { |
758 | if (handler.Match(request, response)) | 836 | // if (handler.Match(request, response)) |
759 | { | 837 | // { |
760 | agentHandler = handler; | 838 | // agentHandler = handler; |
761 | return true; | 839 | // return true; |
762 | } | 840 | // } |
763 | } | 841 | // } |
764 | } | 842 | // } |
765 | 843 | // | |
766 | return false; | 844 | // return false; |
767 | } | 845 | // } |
768 | 846 | ||
769 | /// <summary> | 847 | /// <summary> |
770 | /// Try all the registered xmlrpc handlers when an xmlrpc request is received. | 848 | /// Try all the registered xmlrpc handlers when an xmlrpc request is received. |
@@ -1737,21 +1815,21 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
1737 | m_pollHandlers.Remove(path); | 1815 | m_pollHandlers.Remove(path); |
1738 | } | 1816 | } |
1739 | 1817 | ||
1740 | public bool RemoveAgentHandler(string agent, IHttpAgentHandler handler) | 1818 | // public bool RemoveAgentHandler(string agent, IHttpAgentHandler handler) |
1741 | { | 1819 | // { |
1742 | lock (m_agentHandlers) | 1820 | // lock (m_agentHandlers) |
1743 | { | 1821 | // { |
1744 | IHttpAgentHandler foundHandler; | 1822 | // IHttpAgentHandler foundHandler; |
1745 | 1823 | // | |
1746 | if (m_agentHandlers.TryGetValue(agent, out foundHandler) && foundHandler == handler) | 1824 | // if (m_agentHandlers.TryGetValue(agent, out foundHandler) && foundHandler == handler) |
1747 | { | 1825 | // { |
1748 | m_agentHandlers.Remove(agent); | 1826 | // m_agentHandlers.Remove(agent); |
1749 | return true; | 1827 | // return true; |
1750 | } | 1828 | // } |
1751 | } | 1829 | // } |
1752 | 1830 | // | |
1753 | return false; | 1831 | // return false; |
1754 | } | 1832 | // } |
1755 | 1833 | ||
1756 | public void RemoveXmlRPCHandler(string method) | 1834 | public void RemoveXmlRPCHandler(string method) |
1757 | { | 1835 | { |