aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs')
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs383
1 files changed, 336 insertions, 47 deletions
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index aa49343..f252bd5 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -46,6 +46,7 @@ using CoolHTTPListener = HttpServer.HttpListener;
46using HttpListener=System.Net.HttpListener; 46using HttpListener=System.Net.HttpListener;
47using LogPrio=HttpServer.LogPrio; 47using LogPrio=HttpServer.LogPrio;
48using OpenSim.Framework.Monitoring; 48using OpenSim.Framework.Monitoring;
49using System.IO.Compression;
49 50
50namespace OpenSim.Framework.Servers.HttpServer 51namespace OpenSim.Framework.Servers.HttpServer
51{ 52{
@@ -53,6 +54,16 @@ namespace OpenSim.Framework.Servers.HttpServer
53 { 54 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 private HttpServerLogWriter httpserverlog = new HttpServerLogWriter(); 56 private HttpServerLogWriter httpserverlog = new HttpServerLogWriter();
57 private static Encoding UTF8NoBOM = new System.Text.UTF8Encoding(false);
58
59 /// <summary>
60 /// This is a pending websocket request before it got an sucessful upgrade response.
61 /// The consumer must call handler.HandshakeAndUpgrade() to signal to the handler to
62 /// start the connection and optionally provide an origin authentication method.
63 /// </summary>
64 /// <param name="servicepath"></param>
65 /// <param name="handler"></param>
66 public delegate void WebSocketRequestDelegate(string servicepath, WebSocketHttpServerHandler handler);
56 67
57 /// <summary> 68 /// <summary>
58 /// Gets or sets the debug level. 69 /// Gets or sets the debug level.
@@ -71,12 +82,18 @@ namespace OpenSim.Framework.Servers.HttpServer
71 /// </remarks> 82 /// </remarks>
72 public int RequestNumber { get; private set; } 83 public int RequestNumber { get; private set; }
73 84
85 /// <summary>
86 /// Statistic for holding number of requests processed.
87 /// </summary>
88 private Stat m_requestsProcessedStat;
89
74 private volatile int NotSocketErrors = 0; 90 private volatile int NotSocketErrors = 0;
75 public volatile bool HTTPDRunning = false; 91 public volatile bool HTTPDRunning = false;
76 92
77 // protected HttpListener m_httpListener; 93 // protected HttpListener m_httpListener;
78 protected CoolHTTPListener m_httpListener2; 94 protected CoolHTTPListener m_httpListener2;
79 protected Dictionary<string, XmlRpcMethod> m_rpcHandlers = new Dictionary<string, XmlRpcMethod>(); 95 protected Dictionary<string, XmlRpcMethod> m_rpcHandlers = new Dictionary<string, XmlRpcMethod>();
96 protected Dictionary<string, JsonRPCMethod> jsonRpcHandlers = new Dictionary<string, JsonRPCMethod>();
80 protected Dictionary<string, bool> m_rpcHandlersKeepAlive = new Dictionary<string, bool>(); 97 protected Dictionary<string, bool> m_rpcHandlersKeepAlive = new Dictionary<string, bool>();
81 protected DefaultLLSDMethod m_defaultLlsdHandler = null; // <-- Moving away from the monolithic.. and going to /registered/ 98 protected DefaultLLSDMethod m_defaultLlsdHandler = null; // <-- Moving away from the monolithic.. and going to /registered/
82 protected Dictionary<string, LLSDMethod> m_llsdHandlers = new Dictionary<string, LLSDMethod>(); 99 protected Dictionary<string, LLSDMethod> m_llsdHandlers = new Dictionary<string, LLSDMethod>();
@@ -86,6 +103,9 @@ namespace OpenSim.Framework.Servers.HttpServer
86 protected Dictionary<string, PollServiceEventArgs> m_pollHandlers = 103 protected Dictionary<string, PollServiceEventArgs> m_pollHandlers =
87 new Dictionary<string, PollServiceEventArgs>(); 104 new Dictionary<string, PollServiceEventArgs>();
88 105
106 protected Dictionary<string, WebSocketRequestDelegate> m_WebSocketHandlers =
107 new Dictionary<string, WebSocketRequestDelegate>();
108
89 protected uint m_port; 109 protected uint m_port;
90 protected uint m_sslport; 110 protected uint m_sslport;
91 protected bool m_ssl; 111 protected bool m_ssl;
@@ -95,7 +115,7 @@ namespace OpenSim.Framework.Servers.HttpServer
95 115
96 protected IPAddress m_listenIPAddress = IPAddress.Any; 116 protected IPAddress m_listenIPAddress = IPAddress.Any;
97 117
98 private PollServiceRequestManager m_PollServiceManager; 118 public PollServiceRequestManager PollServiceRequestManager { get; private set; }
99 119
100 public uint SSLPort 120 public uint SSLPort
101 { 121 {
@@ -169,6 +189,22 @@ namespace OpenSim.Framework.Servers.HttpServer
169 } 189 }
170 } 190 }
171 191
192 public void AddWebSocketHandler(string servicepath, WebSocketRequestDelegate handler)
193 {
194 lock (m_WebSocketHandlers)
195 {
196 if (!m_WebSocketHandlers.ContainsKey(servicepath))
197 m_WebSocketHandlers.Add(servicepath, handler);
198 }
199 }
200
201 public void RemoveWebSocketHandler(string servicepath)
202 {
203 lock (m_WebSocketHandlers)
204 if (m_WebSocketHandlers.ContainsKey(servicepath))
205 m_WebSocketHandlers.Remove(servicepath);
206 }
207
172 public List<string> GetStreamHandlerKeys() 208 public List<string> GetStreamHandlerKeys()
173 { 209 {
174 lock (m_streamHandlers) 210 lock (m_streamHandlers)
@@ -217,6 +253,37 @@ namespace OpenSim.Framework.Servers.HttpServer
217 return new List<string>(m_rpcHandlers.Keys); 253 return new List<string>(m_rpcHandlers.Keys);
218 } 254 }
219 255
256 // JsonRPC
257 public bool AddJsonRPCHandler(string method, JsonRPCMethod handler)
258 {
259 lock(jsonRpcHandlers)
260 {
261 jsonRpcHandlers.Add(method, handler);
262 }
263 return true;
264 }
265
266 public JsonRPCMethod GetJsonRPCHandler(string method)
267 {
268 lock (jsonRpcHandlers)
269 {
270 if (jsonRpcHandlers.ContainsKey(method))
271 {
272 return jsonRpcHandlers[method];
273 }
274 else
275 {
276 return null;
277 }
278 }
279 }
280
281 public List<string> GetJsonRpcHandlerKeys()
282 {
283 lock (jsonRpcHandlers)
284 return new List<string>(jsonRpcHandlers.Keys);
285 }
286
220 public bool AddHTTPHandler(string methodName, GenericHTTPMethod handler) 287 public bool AddHTTPHandler(string methodName, GenericHTTPMethod handler)
221 { 288 {
222 //m_log.DebugFormat("[BASE HTTP SERVER]: Registering {0}", methodName); 289 //m_log.DebugFormat("[BASE HTTP SERVER]: Registering {0}", methodName);
@@ -309,7 +376,7 @@ namespace OpenSim.Framework.Servers.HttpServer
309 return true; 376 return true;
310 } 377 }
311 378
312 private void OnRequest(object source, RequestEventArgs args) 379 public void OnRequest(object source, RequestEventArgs args)
313 { 380 {
314 RequestNumber++; 381 RequestNumber++;
315 382
@@ -322,6 +389,8 @@ namespace OpenSim.Framework.Servers.HttpServer
322 389
323 if (TryGetPollServiceHTTPHandler(request.UriPath.ToString(), out psEvArgs)) 390 if (TryGetPollServiceHTTPHandler(request.UriPath.ToString(), out psEvArgs))
324 { 391 {
392 psEvArgs.RequestsReceived++;
393
325 PollServiceHttpRequest psreq = new PollServiceHttpRequest(psEvArgs, context, request); 394 PollServiceHttpRequest psreq = new PollServiceHttpRequest(psEvArgs, context, request);
326 395
327 if (psEvArgs.Request != null) 396 if (psEvArgs.Request != null)
@@ -362,7 +431,7 @@ namespace OpenSim.Framework.Servers.HttpServer
362 psEvArgs.Request(psreq.RequestID, keysvals); 431 psEvArgs.Request(psreq.RequestID, keysvals);
363 } 432 }
364 433
365 m_PollServiceManager.Enqueue(psreq); 434 PollServiceRequestManager.Enqueue(psreq);
366 } 435 }
367 else 436 else
368 { 437 {
@@ -375,11 +444,24 @@ namespace OpenSim.Framework.Servers.HttpServer
375 } 444 }
376 } 445 }
377 446
378 public void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request) 447 private void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request)
379 { 448 {
380 OSHttpRequest req = new OSHttpRequest(context, request); 449 OSHttpRequest req = new OSHttpRequest(context, request);
450 WebSocketRequestDelegate dWebSocketRequestDelegate = null;
451 lock (m_WebSocketHandlers)
452 {
453 if (m_WebSocketHandlers.ContainsKey(req.RawUrl))
454 dWebSocketRequestDelegate = m_WebSocketHandlers[req.RawUrl];
455 }
456 if (dWebSocketRequestDelegate != null)
457 {
458 dWebSocketRequestDelegate(req.Url.AbsolutePath, new WebSocketHttpServerHandler(req, context, 8192));
459 return;
460 }
461
381 OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context); 462 OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context);
382 HandleRequest(req, resp); 463 resp.ReuseContext = true;
464 HandleRequest(req, resp);
383 465
384 // !!!HACK ALERT!!! 466 // !!!HACK ALERT!!!
385 // There seems to be a bug in the underlying http code that makes subsequent requests 467 // There seems to be a bug in the underlying http code that makes subsequent requests
@@ -410,7 +492,9 @@ namespace OpenSim.Framework.Servers.HttpServer
410 { 492 {
411 try 493 try
412 { 494 {
413 SendHTML500(response); 495 byte[] buffer500 = SendHTML500(response);
496 response.OutputStream.Write(buffer500, 0, buffer500.Length);
497 response.Send();
414 } 498 }
415 catch 499 catch
416 { 500 {
@@ -468,7 +552,7 @@ namespace OpenSim.Framework.Servers.HttpServer
468 LogIncomingToStreamHandler(request, requestHandler); 552 LogIncomingToStreamHandler(request, requestHandler);
469 553
470 response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type. 554 response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type.
471 555
472 if (requestHandler is IStreamedRequestHandler) 556 if (requestHandler is IStreamedRequestHandler)
473 { 557 {
474 IStreamedRequestHandler streamedRequestHandler = requestHandler as IStreamedRequestHandler; 558 IStreamedRequestHandler streamedRequestHandler = requestHandler as IStreamedRequestHandler;
@@ -556,10 +640,18 @@ namespace OpenSim.Framework.Servers.HttpServer
556 640
557 buffer = HandleLLSDRequests(request, response); 641 buffer = HandleLLSDRequests(request, response);
558 break; 642 break;
643
644 case "application/json-rpc":
645 if (DebugLevel >= 3)
646 LogIncomingToContentTypeHandler(request);
647
648 buffer = HandleJsonRpcRequests(request, response);
649 break;
559 650
560 case "text/xml": 651 case "text/xml":
561 case "application/xml": 652 case "application/xml":
562 case "application/json": 653 case "application/json":
654
563 default: 655 default:
564 //m_log.Info("[Debug BASE HTTP SERVER]: in default handler"); 656 //m_log.Info("[Debug BASE HTTP SERVER]: in default handler");
565 // Point of note.. the DoWeHaveA methods check for an EXACT path 657 // Point of note.. the DoWeHaveA methods check for an EXACT path
@@ -600,7 +692,24 @@ namespace OpenSim.Framework.Servers.HttpServer
600 692
601 if (buffer != null) 693 if (buffer != null)
602 { 694 {
603 if (!response.SendChunked) 695 if (WebUtil.DebugLevel >= 5)
696 {
697 string output = System.Text.Encoding.UTF8.GetString(buffer);
698
699 if (WebUtil.DebugLevel >= 6)
700 {
701 // Always truncate binary blobs. We don't have a ContentType, so detect them using the request name.
702 if ((requestHandler != null && requestHandler.Name == "GetMesh"))
703 {
704 if (output.Length > WebUtil.MaxRequestDiagLength)
705 output = output.Substring(0, WebUtil.MaxRequestDiagLength) + "...";
706 }
707 }
708
709 WebUtil.LogResponseDetail(RequestNumber, output);
710 }
711
712 if (!response.SendChunked && response.ContentLength64 <= 0)
604 response.ContentLength64 = buffer.LongLength; 713 response.ContentLength64 = buffer.LongLength;
605 714
606 response.OutputStream.Write(buffer, 0, buffer.Length); 715 response.OutputStream.Write(buffer, 0, buffer.Length);
@@ -630,12 +739,20 @@ namespace OpenSim.Framework.Servers.HttpServer
630 } 739 }
631 catch (IOException e) 740 catch (IOException e)
632 { 741 {
633 m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.StackTrace), e); 742 m_log.Error("[BASE HTTP SERVER]: HandleRequest() threw exception ", e);
634 } 743 }
635 catch (Exception e) 744 catch (Exception e)
636 { 745 {
637 m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.StackTrace), e); 746 m_log.Error("[BASE HTTP SERVER]: HandleRequest() threw exception ", e);
638 SendHTML500(response); 747 try
748 {
749 byte[] buffer500 = SendHTML500(response);
750 response.OutputStream.Write(buffer500, 0, buffer500.Length);
751 response.Send();
752 }
753 catch
754 {
755 }
639 } 756 }
640 finally 757 finally
641 { 758 {
@@ -645,7 +762,7 @@ namespace OpenSim.Framework.Servers.HttpServer
645 if (tickdiff > 3000 && requestHandler != null && requestHandler.Name != "GetTexture") 762 if (tickdiff > 3000 && requestHandler != null && requestHandler.Name != "GetTexture")
646 { 763 {
647 m_log.InfoFormat( 764 m_log.InfoFormat(
648 "[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms", 765 "[LOGHTTP] Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms",
649 RequestNumber, 766 RequestNumber,
650 requestMethod, 767 requestMethod,
651 uriString, 768 uriString,
@@ -657,7 +774,7 @@ namespace OpenSim.Framework.Servers.HttpServer
657 else if (DebugLevel >= 4) 774 else if (DebugLevel >= 4)
658 { 775 {
659 m_log.DebugFormat( 776 m_log.DebugFormat(
660 "[BASE HTTP SERVER]: HTTP IN {0} :{1} took {2}ms", 777 "[LOGHTTP] HTTP IN {0} :{1} took {2}ms",
661 RequestNumber, 778 RequestNumber,
662 Port, 779 Port,
663 tickdiff); 780 tickdiff);
@@ -668,7 +785,7 @@ namespace OpenSim.Framework.Servers.HttpServer
668 private void LogIncomingToStreamHandler(OSHttpRequest request, IRequestHandler requestHandler) 785 private void LogIncomingToStreamHandler(OSHttpRequest request, IRequestHandler requestHandler)
669 { 786 {
670 m_log.DebugFormat( 787 m_log.DebugFormat(
671 "[BASE HTTP SERVER]: HTTP IN {0} :{1} stream handler {2} {3} {4} {5} from {6}", 788 "[LOGHTTP] HTTP IN {0} :{1} stream handler {2} {3} {4} {5} from {6}",
672 RequestNumber, 789 RequestNumber,
673 Port, 790 Port,
674 request.HttpMethod, 791 request.HttpMethod,
@@ -684,10 +801,10 @@ namespace OpenSim.Framework.Servers.HttpServer
684 private void LogIncomingToContentTypeHandler(OSHttpRequest request) 801 private void LogIncomingToContentTypeHandler(OSHttpRequest request)
685 { 802 {
686 m_log.DebugFormat( 803 m_log.DebugFormat(
687 "[BASE HTTP SERVER]: HTTP IN {0} :{1} {2} content type handler {3} {4} from {5}", 804 "[LOGHTTP] HTTP IN {0} :{1} {2} content type handler {3} {4} from {5}",
688 RequestNumber, 805 RequestNumber,
689 Port, 806 Port,
690 (request.ContentType == null || request.ContentType == "") ? "not set" : request.ContentType, 807 string.IsNullOrEmpty(request.ContentType) ? "not set" : request.ContentType,
691 request.HttpMethod, 808 request.HttpMethod,
692 request.Url.PathAndQuery, 809 request.Url.PathAndQuery,
693 request.RemoteIPEndPoint); 810 request.RemoteIPEndPoint);
@@ -699,7 +816,7 @@ namespace OpenSim.Framework.Servers.HttpServer
699 private void LogIncomingToXmlRpcHandler(OSHttpRequest request) 816 private void LogIncomingToXmlRpcHandler(OSHttpRequest request)
700 { 817 {
701 m_log.DebugFormat( 818 m_log.DebugFormat(
702 "[BASE HTTP SERVER]: HTTP IN {0} :{1} assumed generic XMLRPC request {2} {3} from {4}", 819 "[LOGHTTP] HTTP IN {0} :{1} assumed generic XMLRPC request {2} {3} from {4}",
703 RequestNumber, 820 RequestNumber,
704 Port, 821 Port,
705 request.HttpMethod, 822 request.HttpMethod,
@@ -712,29 +829,49 @@ namespace OpenSim.Framework.Servers.HttpServer
712 829
713 private void LogIncomingInDetail(OSHttpRequest request) 830 private void LogIncomingInDetail(OSHttpRequest request)
714 { 831 {
715 using (StreamReader reader = new StreamReader(Util.Copy(request.InputStream), Encoding.UTF8)) 832 if (request.ContentType == "application/octet-stream")
716 { 833 return; // never log these; they're just binary data
717 string output;
718 834
719 if (DebugLevel == 5) 835 Stream inputStream = Util.Copy(request.InputStream);
836 Stream innerStream = null;
837 try
838 {
839 if ((request.Headers["Content-Encoding"] == "gzip") || (request.Headers["X-Content-Encoding"] == "gzip"))
720 { 840 {
721 const int sampleLength = 80; 841 innerStream = inputStream;
722 char[] sampleChars = new char[sampleLength + 3]; 842 inputStream = new GZipStream(innerStream, System.IO.Compression.CompressionMode.Decompress);
723 reader.Read(sampleChars, 0, sampleLength);
724 sampleChars[80] = '.';
725 sampleChars[81] = '.';
726 sampleChars[82] = '.';
727 output = new string(sampleChars);
728 } 843 }
729 else 844
845 using (StreamReader reader = new StreamReader(inputStream, Encoding.UTF8))
730 { 846 {
731 output = reader.ReadToEnd(); 847 string output;
732 }
733 848
734 m_log.DebugFormat("[BASE HTTP SERVER]: {0}", output.Replace("\n", @"\n")); 849 if (DebugLevel == 5)
850 {
851 char[] chars = new char[WebUtil.MaxRequestDiagLength + 1]; // +1 so we know to add "..." only if needed
852 int len = reader.Read(chars, 0, WebUtil.MaxRequestDiagLength + 1);
853 output = new string(chars, 0, Math.Min(len, WebUtil.MaxRequestDiagLength));
854 if (len > WebUtil.MaxRequestDiagLength)
855 output += "...";
856 }
857 else
858 {
859 output = reader.ReadToEnd();
860 }
861
862 m_log.DebugFormat("[LOGHTTP] {0}", Util.BinaryToASCII(output));
863 }
864 }
865 finally
866 {
867 if (innerStream != null)
868 innerStream.Dispose();
869 inputStream.Dispose();
735 } 870 }
736 } 871 }
737 872
873 private readonly string HANDLER_SEPARATORS = "/?&#-";
874
738 private bool TryGetStreamHandler(string handlerKey, out IRequestHandler streamHandler) 875 private bool TryGetStreamHandler(string handlerKey, out IRequestHandler streamHandler)
739 { 876 {
740 string bestMatch = null; 877 string bestMatch = null;
@@ -743,7 +880,8 @@ namespace OpenSim.Framework.Servers.HttpServer
743 { 880 {
744 foreach (string pattern in m_streamHandlers.Keys) 881 foreach (string pattern in m_streamHandlers.Keys)
745 { 882 {
746 if (handlerKey.StartsWith(pattern)) 883 if ((handlerKey == pattern)
884 || (handlerKey.StartsWith(pattern) && (HANDLER_SEPARATORS.IndexOf(handlerKey[pattern.Length]) >= 0)))
747 { 885 {
748 if (String.IsNullOrEmpty(bestMatch) || pattern.Length > bestMatch.Length) 886 if (String.IsNullOrEmpty(bestMatch) || pattern.Length > bestMatch.Length)
749 { 887 {
@@ -773,7 +911,8 @@ namespace OpenSim.Framework.Servers.HttpServer
773 { 911 {
774 foreach (string pattern in m_pollHandlers.Keys) 912 foreach (string pattern in m_pollHandlers.Keys)
775 { 913 {
776 if (handlerKey.StartsWith(pattern)) 914 if ((handlerKey == pattern)
915 || (handlerKey.StartsWith(pattern) && (HANDLER_SEPARATORS.IndexOf(handlerKey[pattern.Length]) >= 0)))
777 { 916 {
778 if (String.IsNullOrEmpty(bestMatch) || pattern.Length > bestMatch.Length) 917 if (String.IsNullOrEmpty(bestMatch) || pattern.Length > bestMatch.Length)
779 { 918 {
@@ -805,7 +944,8 @@ namespace OpenSim.Framework.Servers.HttpServer
805 { 944 {
806 foreach (string pattern in m_HTTPHandlers.Keys) 945 foreach (string pattern in m_HTTPHandlers.Keys)
807 { 946 {
808 if (handlerKey.StartsWith(pattern)) 947 if ((handlerKey == pattern)
948 || (handlerKey.StartsWith(pattern) && (HANDLER_SEPARATORS.IndexOf(handlerKey[pattern.Length]) >= 0)))
809 { 949 {
810 if (String.IsNullOrEmpty(bestMatch) || pattern.Length > bestMatch.Length) 950 if (String.IsNullOrEmpty(bestMatch) || pattern.Length > bestMatch.Length)
811 { 951 {
@@ -854,16 +994,33 @@ namespace OpenSim.Framework.Servers.HttpServer
854 /// <param name="response"></param> 994 /// <param name="response"></param>
855 private byte[] HandleXmlRpcRequests(OSHttpRequest request, OSHttpResponse response) 995 private byte[] HandleXmlRpcRequests(OSHttpRequest request, OSHttpResponse response)
856 { 996 {
997 String requestBody;
998
857 Stream requestStream = request.InputStream; 999 Stream requestStream = request.InputStream;
1000 Stream innerStream = null;
1001 try
1002 {
1003 if ((request.Headers["Content-Encoding"] == "gzip") || (request.Headers["X-Content-Encoding"] == "gzip"))
1004 {
1005 innerStream = requestStream;
1006 requestStream = new GZipStream(innerStream, System.IO.Compression.CompressionMode.Decompress);
1007 }
858 1008
859 Encoding encoding = Encoding.UTF8; 1009 using (StreamReader reader = new StreamReader(requestStream, Encoding.UTF8))
860 StreamReader reader = new StreamReader(requestStream, encoding); 1010 {
1011 requestBody = reader.ReadToEnd();
1012 }
1013 }
1014 finally
1015 {
1016 if (innerStream != null)
1017 innerStream.Dispose();
1018 requestStream.Dispose();
1019 }
861 1020
862 string requestBody = reader.ReadToEnd();
863 reader.Close();
864 requestStream.Close();
865 //m_log.Debug(requestBody); 1021 //m_log.Debug(requestBody);
866 requestBody = requestBody.Replace("<base64></base64>", ""); 1022 requestBody = requestBody.Replace("<base64></base64>", "");
1023
867 string responseString = String.Empty; 1024 string responseString = String.Empty;
868 XmlRpcRequest xmlRprcRequest = null; 1025 XmlRpcRequest xmlRprcRequest = null;
869 1026
@@ -958,7 +1115,19 @@ namespace OpenSim.Framework.Servers.HttpServer
958 } 1115 }
959 1116
960 response.ContentType = "text/xml"; 1117 response.ContentType = "text/xml";
961 responseString = XmlRpcResponseSerializer.Singleton.Serialize(xmlRpcResponse); 1118 using (MemoryStream outs = new MemoryStream())
1119 using (XmlTextWriter writer = new XmlTextWriter(outs, UTF8NoBOM))
1120 {
1121 writer.Formatting = Formatting.None;
1122 XmlRpcResponseSerializer.Singleton.Serialize(writer, xmlRpcResponse);
1123 writer.Flush();
1124 outs.Flush();
1125 outs.Position = 0;
1126 using (StreamReader sr = new StreamReader(outs))
1127 {
1128 responseString = sr.ReadToEnd();
1129 }
1130 }
962 } 1131 }
963 else 1132 else
964 { 1133 {
@@ -985,6 +1154,93 @@ namespace OpenSim.Framework.Servers.HttpServer
985 return buffer; 1154 return buffer;
986 } 1155 }
987 1156
1157 // JsonRpc (v2.0 only)
1158 // Batch requests not yet supported
1159 private byte[] HandleJsonRpcRequests(OSHttpRequest request, OSHttpResponse response)
1160 {
1161 Stream requestStream = request.InputStream;
1162 JsonRpcResponse jsonRpcResponse = new JsonRpcResponse();
1163 OSDMap jsonRpcRequest = null;
1164
1165 try
1166 {
1167 jsonRpcRequest = (OSDMap)OSDParser.DeserializeJson(requestStream);
1168 }
1169 catch (LitJson.JsonException e)
1170 {
1171 jsonRpcResponse.Error.Code = ErrorCode.InternalError;
1172 jsonRpcResponse.Error.Message = e.Message;
1173 }
1174
1175 requestStream.Close();
1176
1177 if (jsonRpcRequest != null)
1178 {
1179 if (jsonRpcRequest.ContainsKey("jsonrpc") || jsonRpcRequest["jsonrpc"].AsString() == "2.0")
1180 {
1181 jsonRpcResponse.JsonRpc = "2.0";
1182
1183 // If we have no id, then it's a "notification"
1184 if (jsonRpcRequest.ContainsKey("id"))
1185 {
1186 jsonRpcResponse.Id = jsonRpcRequest["id"].AsString();
1187 }
1188
1189 string methodname = jsonRpcRequest["method"];
1190 JsonRPCMethod method;
1191
1192 if (jsonRpcHandlers.ContainsKey(methodname))
1193 {
1194 lock(jsonRpcHandlers)
1195 {
1196 jsonRpcHandlers.TryGetValue(methodname, out method);
1197 }
1198 bool res = false;
1199 try
1200 {
1201 res = method(jsonRpcRequest, ref jsonRpcResponse);
1202 if(!res)
1203 {
1204 // The handler sent back an unspecified error
1205 if(jsonRpcResponse.Error.Code == 0)
1206 {
1207 jsonRpcResponse.Error.Code = ErrorCode.InternalError;
1208 }
1209 }
1210 }
1211 catch (Exception e)
1212 {
1213 string ErrorMessage = string.Format("[BASE HTTP SERVER]: Json-Rpc Handler Error method {0} - {1}", methodname, e.Message);
1214 m_log.Error(ErrorMessage);
1215 jsonRpcResponse.Error.Code = ErrorCode.InternalError;
1216 jsonRpcResponse.Error.Message = ErrorMessage;
1217 }
1218 }
1219 else // Error no hanlder defined for requested method
1220 {
1221 jsonRpcResponse.Error.Code = ErrorCode.InvalidRequest;
1222 jsonRpcResponse.Error.Message = string.Format ("No handler defined for {0}", methodname);
1223 }
1224 }
1225 else // not json-rpc 2.0 could be v1
1226 {
1227 jsonRpcResponse.Error.Code = ErrorCode.InvalidRequest;
1228 jsonRpcResponse.Error.Message = "Must be valid json-rpc 2.0 see: http://www.jsonrpc.org/specification";
1229
1230 if (jsonRpcRequest.ContainsKey("id"))
1231 jsonRpcResponse.Id = jsonRpcRequest["id"].AsString();
1232 }
1233 }
1234
1235 response.KeepAlive = true;
1236 string responseData = string.Empty;
1237
1238 responseData = jsonRpcResponse.Serialize();
1239
1240 byte[] buffer = Encoding.UTF8.GetBytes(responseData);
1241 return buffer;
1242 }
1243
988 private byte[] HandleLLSDRequests(OSHttpRequest request, OSHttpResponse response) 1244 private byte[] HandleLLSDRequests(OSHttpRequest request, OSHttpResponse response)
989 { 1245 {
990 //m_log.Warn("[BASE HTTP SERVER]: We've figured out it's a LLSD Request"); 1246 //m_log.Warn("[BASE HTTP SERVER]: We've figured out it's a LLSD Request");
@@ -1575,16 +1831,24 @@ namespace OpenSim.Framework.Servers.HttpServer
1575 response.SendChunked = false; 1831 response.SendChunked = false;
1576 response.ContentLength64 = buffer.Length; 1832 response.ContentLength64 = buffer.Length;
1577 response.ContentEncoding = Encoding.UTF8; 1833 response.ContentEncoding = Encoding.UTF8;
1578 1834
1835
1579 return buffer; 1836 return buffer;
1580 } 1837 }
1581 1838
1582 public void Start() 1839 public void Start()
1583 { 1840 {
1584 StartHTTP(); 1841 Start(true);
1585 } 1842 }
1586 1843
1587 private void StartHTTP() 1844 /// <summary>
1845 /// Start the http server
1846 /// </summary>
1847 /// <param name='processPollRequestsAsync'>
1848 /// If true then poll responses are performed asynchronsly.
1849 /// Option exists to allow regression tests to perform processing synchronously.
1850 /// </param>
1851 public void Start(bool performPollResponsesAsync)
1588 { 1852 {
1589 m_log.InfoFormat( 1853 m_log.InfoFormat(
1590 "[BASE HTTP SERVER]: Starting {0} server on port {1}", UseSSL ? "HTTPS" : "HTTP", Port); 1854 "[BASE HTTP SERVER]: Starting {0} server on port {1}", UseSSL ? "HTTPS" : "HTTP", Port);
@@ -1622,8 +1886,9 @@ namespace OpenSim.Framework.Servers.HttpServer
1622 m_httpListener2.Start(64); 1886 m_httpListener2.Start(64);
1623 1887
1624 // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events 1888 // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events
1625 m_PollServiceManager = new PollServiceRequestManager(this, 3, 25000); 1889 PollServiceRequestManager = new PollServiceRequestManager(this, performPollResponsesAsync, 3, 25000);
1626 m_PollServiceManager.Start(); 1890 PollServiceRequestManager.Start();
1891
1627 HTTPDRunning = true; 1892 HTTPDRunning = true;
1628 1893
1629 //HttpListenerContext context; 1894 //HttpListenerContext context;
@@ -1642,6 +1907,21 @@ namespace OpenSim.Framework.Servers.HttpServer
1642 // useful without inbound HTTP. 1907 // useful without inbound HTTP.
1643 throw e; 1908 throw e;
1644 } 1909 }
1910
1911 m_requestsProcessedStat
1912 = new Stat(
1913 "HTTPRequestsServed",
1914 "Number of inbound HTTP requests processed",
1915 "",
1916 "requests",
1917 "httpserver",
1918 Port.ToString(),
1919 StatType.Pull,
1920 MeasuresOfInterest.AverageChangeOverTime,
1921 stat => stat.Value = RequestNumber,
1922 StatVerbosity.Debug);
1923
1924 StatsManager.RegisterStat(m_requestsProcessedStat);
1645 } 1925 }
1646 1926
1647 public void httpServerDisconnectMonitor(IHttpClientContext source, SocketError err) 1927 public void httpServerDisconnectMonitor(IHttpClientContext source, SocketError err)
@@ -1672,9 +1952,12 @@ namespace OpenSim.Framework.Servers.HttpServer
1672 public void Stop() 1952 public void Stop()
1673 { 1953 {
1674 HTTPDRunning = false; 1954 HTTPDRunning = false;
1955
1956 StatsManager.DeregisterStat(m_requestsProcessedStat);
1957
1675 try 1958 try
1676 { 1959 {
1677 m_PollServiceManager.Stop(); 1960 PollServiceRequestManager.Stop();
1678 1961
1679 m_httpListener2.ExceptionThrown -= httpServerException; 1962 m_httpListener2.ExceptionThrown -= httpServerException;
1680 //m_httpListener2.DisconnectHandler = null; 1963 //m_httpListener2.DisconnectHandler = null;
@@ -1741,6 +2024,12 @@ namespace OpenSim.Framework.Servers.HttpServer
1741 m_rpcHandlers.Remove(method); 2024 m_rpcHandlers.Remove(method);
1742 } 2025 }
1743 2026
2027 public void RemoveJsonRPCHandler(string method)
2028 {
2029 lock(jsonRpcHandlers)
2030 jsonRpcHandlers.Remove(method);
2031 }
2032
1744 public bool RemoveLLSDHandler(string path, LLSDMethod handler) 2033 public bool RemoveLLSDHandler(string path, LLSDMethod handler)
1745 { 2034 {
1746 lock (m_llsdHandlers) 2035 lock (m_llsdHandlers)