diff options
Merge branch 'avination-current' of ssh://3dhosting.de/var/git/careminster into avination-current
Conflicts:
bin/Regions/Regions.ini.example
Diffstat (limited to 'OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs')
-rw-r--r-- | OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs | 253 |
1 files changed, 195 insertions, 58 deletions
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 77fce9e..97035e3 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs | |||
@@ -54,6 +54,16 @@ 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 | |||
58 | /// <summary> | ||
59 | /// This is a pending websocket request before it got an sucessful upgrade response. | ||
60 | /// The consumer must call handler.HandshakeAndUpgrade() to signal to the handler to | ||
61 | /// start the connection and optionally provide an origin authentication method. | ||
62 | /// </summary> | ||
63 | /// <param name="servicepath"></param> | ||
64 | /// <param name="handler"></param> | ||
65 | public delegate void WebSocketRequestDelegate(string servicepath, WebSocketHttpServerHandler handler); | ||
66 | |||
57 | /// <summary> | 67 | /// <summary> |
58 | /// Gets or sets the debug level. | 68 | /// Gets or sets the debug level. |
59 | /// </summary> | 69 | /// </summary> |
@@ -77,6 +87,7 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
77 | // protected HttpListener m_httpListener; | 87 | // protected HttpListener m_httpListener; |
78 | protected CoolHTTPListener m_httpListener2; | 88 | protected CoolHTTPListener m_httpListener2; |
79 | protected Dictionary<string, XmlRpcMethod> m_rpcHandlers = new Dictionary<string, XmlRpcMethod>(); | 89 | protected Dictionary<string, XmlRpcMethod> m_rpcHandlers = new Dictionary<string, XmlRpcMethod>(); |
90 | protected Dictionary<string, JsonRPCMethod> jsonRpcHandlers = new Dictionary<string, JsonRPCMethod>(); | ||
80 | protected Dictionary<string, bool> m_rpcHandlersKeepAlive = new Dictionary<string, bool>(); | 91 | 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/ | 92 | 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>(); | 93 | protected Dictionary<string, LLSDMethod> m_llsdHandlers = new Dictionary<string, LLSDMethod>(); |
@@ -86,6 +97,9 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
86 | protected Dictionary<string, PollServiceEventArgs> m_pollHandlers = | 97 | protected Dictionary<string, PollServiceEventArgs> m_pollHandlers = |
87 | new Dictionary<string, PollServiceEventArgs>(); | 98 | new Dictionary<string, PollServiceEventArgs>(); |
88 | 99 | ||
100 | protected Dictionary<string, WebSocketRequestDelegate> m_WebSocketHandlers = | ||
101 | new Dictionary<string, WebSocketRequestDelegate>(); | ||
102 | |||
89 | protected uint m_port; | 103 | protected uint m_port; |
90 | protected uint m_sslport; | 104 | protected uint m_sslport; |
91 | protected bool m_ssl; | 105 | protected bool m_ssl; |
@@ -169,6 +183,22 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
169 | } | 183 | } |
170 | } | 184 | } |
171 | 185 | ||
186 | public void AddWebSocketHandler(string servicepath, WebSocketRequestDelegate handler) | ||
187 | { | ||
188 | lock (m_WebSocketHandlers) | ||
189 | { | ||
190 | if (!m_WebSocketHandlers.ContainsKey(servicepath)) | ||
191 | m_WebSocketHandlers.Add(servicepath, handler); | ||
192 | } | ||
193 | } | ||
194 | |||
195 | public void RemoveWebSocketHandler(string servicepath) | ||
196 | { | ||
197 | lock (m_WebSocketHandlers) | ||
198 | if (m_WebSocketHandlers.ContainsKey(servicepath)) | ||
199 | m_WebSocketHandlers.Remove(servicepath); | ||
200 | } | ||
201 | |||
172 | public List<string> GetStreamHandlerKeys() | 202 | public List<string> GetStreamHandlerKeys() |
173 | { | 203 | { |
174 | lock (m_streamHandlers) | 204 | lock (m_streamHandlers) |
@@ -217,6 +247,37 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
217 | return new List<string>(m_rpcHandlers.Keys); | 247 | return new List<string>(m_rpcHandlers.Keys); |
218 | } | 248 | } |
219 | 249 | ||
250 | // JsonRPC | ||
251 | public bool AddJsonRPCHandler(string method, JsonRPCMethod handler) | ||
252 | { | ||
253 | lock(jsonRpcHandlers) | ||
254 | { | ||
255 | jsonRpcHandlers.Add(method, handler); | ||
256 | } | ||
257 | return true; | ||
258 | } | ||
259 | |||
260 | public JsonRPCMethod GetJsonRPCHandler(string method) | ||
261 | { | ||
262 | lock (jsonRpcHandlers) | ||
263 | { | ||
264 | if (jsonRpcHandlers.ContainsKey(method)) | ||
265 | { | ||
266 | return jsonRpcHandlers[method]; | ||
267 | } | ||
268 | else | ||
269 | { | ||
270 | return null; | ||
271 | } | ||
272 | } | ||
273 | } | ||
274 | |||
275 | public List<string> GetJsonRpcHandlerKeys() | ||
276 | { | ||
277 | lock (jsonRpcHandlers) | ||
278 | return new List<string>(jsonRpcHandlers.Keys); | ||
279 | } | ||
280 | |||
220 | public bool AddHTTPHandler(string methodName, GenericHTTPMethod handler) | 281 | public bool AddHTTPHandler(string methodName, GenericHTTPMethod handler) |
221 | { | 282 | { |
222 | //m_log.DebugFormat("[BASE HTTP SERVER]: Registering {0}", methodName); | 283 | //m_log.DebugFormat("[BASE HTTP SERVER]: Registering {0}", methodName); |
@@ -378,9 +439,24 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
378 | 439 | ||
379 | public void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request) | 440 | public void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request) |
380 | { | 441 | { |
442 | |||
381 | OSHttpRequest req = new OSHttpRequest(context, request); | 443 | OSHttpRequest req = new OSHttpRequest(context, request); |
444 | WebSocketRequestDelegate dWebSocketRequestDelegate = null; | ||
445 | lock (m_WebSocketHandlers) | ||
446 | { | ||
447 | if (m_WebSocketHandlers.ContainsKey(req.RawUrl)) | ||
448 | dWebSocketRequestDelegate = m_WebSocketHandlers[req.RawUrl]; | ||
449 | } | ||
450 | if (dWebSocketRequestDelegate != null) | ||
451 | { | ||
452 | dWebSocketRequestDelegate(req.Url.AbsolutePath, new WebSocketHttpServerHandler(req, context, 8192)); | ||
453 | return; | ||
454 | } | ||
455 | |||
382 | OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context); | 456 | OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context); |
457 | |||
383 | HandleRequest(req, resp); | 458 | HandleRequest(req, resp); |
459 | |||
384 | 460 | ||
385 | // !!!HACK ALERT!!! | 461 | // !!!HACK ALERT!!! |
386 | // There seems to be a bug in the underlying http code that makes subsequent requests | 462 | // There seems to be a bug in the underlying http code that makes subsequent requests |
@@ -411,7 +487,9 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
411 | { | 487 | { |
412 | try | 488 | try |
413 | { | 489 | { |
414 | SendHTML500(response); | 490 | byte[] buffer500 = SendHTML500(response); |
491 | response.Body.Write(buffer500,0,buffer500.Length); | ||
492 | response.Body.Close(); | ||
415 | } | 493 | } |
416 | catch | 494 | catch |
417 | { | 495 | { |
@@ -437,7 +515,7 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
437 | // reqnum = String.Format("{0}:{1}",request.RemoteIPEndPoint,request.Headers["opensim-request-id"]); | 515 | // reqnum = String.Format("{0}:{1}",request.RemoteIPEndPoint,request.Headers["opensim-request-id"]); |
438 | //m_log.DebugFormat("[BASE HTTP SERVER]: <{0}> handle request for {1}",reqnum,request.RawUrl); | 516 | //m_log.DebugFormat("[BASE HTTP SERVER]: <{0}> handle request for {1}",reqnum,request.RawUrl); |
439 | 517 | ||
440 | Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true); | 518 | Culture.SetCurrentCulture(); |
441 | 519 | ||
442 | // // This is the REST agent interface. We require an agent to properly identify | 520 | // // This is the REST agent interface. We require an agent to properly identify |
443 | // // itself. If the REST handler recognizes the prefix it will attempt to | 521 | // // itself. If the REST handler recognizes the prefix it will attempt to |
@@ -469,7 +547,7 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
469 | LogIncomingToStreamHandler(request, requestHandler); | 547 | LogIncomingToStreamHandler(request, requestHandler); |
470 | 548 | ||
471 | response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type. | 549 | response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type. |
472 | 550 | ||
473 | if (requestHandler is IStreamedRequestHandler) | 551 | if (requestHandler is IStreamedRequestHandler) |
474 | { | 552 | { |
475 | IStreamedRequestHandler streamedRequestHandler = requestHandler as IStreamedRequestHandler; | 553 | IStreamedRequestHandler streamedRequestHandler = requestHandler as IStreamedRequestHandler; |
@@ -557,10 +635,18 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
557 | 635 | ||
558 | buffer = HandleLLSDRequests(request, response); | 636 | buffer = HandleLLSDRequests(request, response); |
559 | break; | 637 | break; |
638 | |||
639 | case "application/json-rpc": | ||
640 | if (DebugLevel >= 3) | ||
641 | LogIncomingToContentTypeHandler(request); | ||
642 | |||
643 | buffer = HandleJsonRpcRequests(request, response); | ||
644 | break; | ||
560 | 645 | ||
561 | case "text/xml": | 646 | case "text/xml": |
562 | case "application/xml": | 647 | case "application/xml": |
563 | case "application/json": | 648 | case "application/json": |
649 | |||
564 | default: | 650 | default: |
565 | //m_log.Info("[Debug BASE HTTP SERVER]: in default handler"); | 651 | //m_log.Info("[Debug BASE HTTP SERVER]: in default handler"); |
566 | // Point of note.. the DoWeHaveA methods check for an EXACT path | 652 | // Point of note.. the DoWeHaveA methods check for an EXACT path |
@@ -636,7 +722,15 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
636 | catch (Exception e) | 722 | catch (Exception e) |
637 | { | 723 | { |
638 | m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.StackTrace), e); | 724 | m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.StackTrace), e); |
639 | SendHTML500(response); | 725 | try |
726 | { | ||
727 | byte[] buffer500 = SendHTML500(response); | ||
728 | response.Body.Write(buffer500, 0, buffer500.Length); | ||
729 | response.Body.Close(); | ||
730 | } | ||
731 | catch | ||
732 | { | ||
733 | } | ||
640 | } | 734 | } |
641 | finally | 735 | finally |
642 | { | 736 | { |
@@ -986,6 +1080,93 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
986 | return buffer; | 1080 | return buffer; |
987 | } | 1081 | } |
988 | 1082 | ||
1083 | // JsonRpc (v2.0 only) | ||
1084 | // Batch requests not yet supported | ||
1085 | private byte[] HandleJsonRpcRequests(OSHttpRequest request, OSHttpResponse response) | ||
1086 | { | ||
1087 | Stream requestStream = request.InputStream; | ||
1088 | JsonRpcResponse jsonRpcResponse = new JsonRpcResponse(); | ||
1089 | OSDMap jsonRpcRequest = null; | ||
1090 | |||
1091 | try | ||
1092 | { | ||
1093 | jsonRpcRequest = (OSDMap)OSDParser.DeserializeJson(requestStream); | ||
1094 | } | ||
1095 | catch (LitJson.JsonException e) | ||
1096 | { | ||
1097 | jsonRpcResponse.Error.Code = ErrorCode.InternalError; | ||
1098 | jsonRpcResponse.Error.Message = e.Message; | ||
1099 | } | ||
1100 | |||
1101 | requestStream.Close(); | ||
1102 | |||
1103 | if (jsonRpcRequest != null) | ||
1104 | { | ||
1105 | if (jsonRpcRequest.ContainsKey("jsonrpc") || jsonRpcRequest["jsonrpc"].AsString() == "2.0") | ||
1106 | { | ||
1107 | jsonRpcResponse.JsonRpc = "2.0"; | ||
1108 | |||
1109 | // If we have no id, then it's a "notification" | ||
1110 | if (jsonRpcRequest.ContainsKey("id")) | ||
1111 | { | ||
1112 | jsonRpcResponse.Id = jsonRpcRequest["id"].AsString(); | ||
1113 | } | ||
1114 | |||
1115 | string methodname = jsonRpcRequest["method"]; | ||
1116 | JsonRPCMethod method; | ||
1117 | |||
1118 | if (jsonRpcHandlers.ContainsKey(methodname)) | ||
1119 | { | ||
1120 | lock(jsonRpcHandlers) | ||
1121 | { | ||
1122 | jsonRpcHandlers.TryGetValue(methodname, out method); | ||
1123 | } | ||
1124 | bool res = false; | ||
1125 | try | ||
1126 | { | ||
1127 | res = method(jsonRpcRequest, ref jsonRpcResponse); | ||
1128 | if(!res) | ||
1129 | { | ||
1130 | // The handler sent back an unspecified error | ||
1131 | if(jsonRpcResponse.Error.Code == 0) | ||
1132 | { | ||
1133 | jsonRpcResponse.Error.Code = ErrorCode.InternalError; | ||
1134 | } | ||
1135 | } | ||
1136 | } | ||
1137 | catch (Exception e) | ||
1138 | { | ||
1139 | string ErrorMessage = string.Format("[BASE HTTP SERVER]: Json-Rpc Handler Error method {0} - {1}", methodname, e.Message); | ||
1140 | m_log.Error(ErrorMessage); | ||
1141 | jsonRpcResponse.Error.Code = ErrorCode.InternalError; | ||
1142 | jsonRpcResponse.Error.Message = ErrorMessage; | ||
1143 | } | ||
1144 | } | ||
1145 | else // Error no hanlder defined for requested method | ||
1146 | { | ||
1147 | jsonRpcResponse.Error.Code = ErrorCode.InvalidRequest; | ||
1148 | jsonRpcResponse.Error.Message = string.Format ("No handler defined for {0}", methodname); | ||
1149 | } | ||
1150 | } | ||
1151 | else // not json-rpc 2.0 could be v1 | ||
1152 | { | ||
1153 | jsonRpcResponse.Error.Code = ErrorCode.InvalidRequest; | ||
1154 | jsonRpcResponse.Error.Message = "Must be valid json-rpc 2.0 see: http://www.jsonrpc.org/specification"; | ||
1155 | |||
1156 | if (jsonRpcRequest.ContainsKey("id")) | ||
1157 | jsonRpcResponse.Id = jsonRpcRequest["id"].AsString(); | ||
1158 | } | ||
1159 | } | ||
1160 | |||
1161 | response.KeepAlive = true; | ||
1162 | string responseData = string.Empty; | ||
1163 | |||
1164 | responseData = jsonRpcResponse.Serialize(); | ||
1165 | |||
1166 | byte[] buffer = Encoding.UTF8.GetBytes(responseData); | ||
1167 | return buffer; | ||
1168 | } | ||
1169 | |||
989 | private byte[] HandleLLSDRequests(OSHttpRequest request, OSHttpResponse response) | 1170 | private byte[] HandleLLSDRequests(OSHttpRequest request, OSHttpResponse response) |
990 | { | 1171 | { |
991 | //m_log.Warn("[BASE HTTP SERVER]: We've figured out it's a LLSD Request"); | 1172 | //m_log.Warn("[BASE HTTP SERVER]: We've figured out it's a LLSD Request"); |
@@ -1283,59 +1464,6 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
1283 | map["login"] = OSD.FromString("false"); | 1464 | map["login"] = OSD.FromString("false"); |
1284 | return map; | 1465 | return map; |
1285 | } | 1466 | } |
1286 | /// <summary> | ||
1287 | /// A specific agent handler was provided. Such a handler is expecetd to have an | ||
1288 | /// intimate, and highly specific relationship with the client. Consequently, | ||
1289 | /// nothing is done here. | ||
1290 | /// </summary> | ||
1291 | /// <param name="handler"></param> | ||
1292 | /// <param name="request"></param> | ||
1293 | /// <param name="response"></param> | ||
1294 | |||
1295 | private bool HandleAgentRequest(IHttpAgentHandler handler, OSHttpRequest request, OSHttpResponse response) | ||
1296 | { | ||
1297 | // In the case of REST, then handler is responsible for ALL aspects of | ||
1298 | // the request/response handling. Nothing is done here, not even encoding. | ||
1299 | |||
1300 | try | ||
1301 | { | ||
1302 | return handler.Handle(request, response); | ||
1303 | } | ||
1304 | catch (Exception e) | ||
1305 | { | ||
1306 | // If the handler did in fact close the stream, then this will blow | ||
1307 | // chunks. So that that doesn't disturb anybody we throw away any | ||
1308 | // and all exceptions raised. We've done our best to release the | ||
1309 | // client. | ||
1310 | try | ||
1311 | { | ||
1312 | m_log.Warn("[HTTP-AGENT]: Error - " + e.Message); | ||
1313 | response.SendChunked = false; | ||
1314 | response.KeepAlive = true; | ||
1315 | response.StatusCode = (int)OSHttpStatusCode.ServerErrorInternalError; | ||
1316 | //response.OutputStream.Close(); | ||
1317 | try | ||
1318 | { | ||
1319 | response.Send(); | ||
1320 | //response.FreeContext(); | ||
1321 | } | ||
1322 | catch (SocketException f) | ||
1323 | { | ||
1324 | // This has to be here to prevent a Linux/Mono crash | ||
1325 | m_log.Warn( | ||
1326 | String.Format("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux. ", f.Message), f); | ||
1327 | } | ||
1328 | } | ||
1329 | catch(Exception) | ||
1330 | { | ||
1331 | } | ||
1332 | } | ||
1333 | |||
1334 | // Indicate that the request has been "handled" | ||
1335 | |||
1336 | return true; | ||
1337 | |||
1338 | } | ||
1339 | 1467 | ||
1340 | public byte[] HandleHTTPRequest(OSHttpRequest request, OSHttpResponse response) | 1468 | public byte[] HandleHTTPRequest(OSHttpRequest request, OSHttpResponse response) |
1341 | { | 1469 | { |
@@ -1674,7 +1802,8 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
1674 | response.SendChunked = false; | 1802 | response.SendChunked = false; |
1675 | response.ContentLength64 = buffer.Length; | 1803 | response.ContentLength64 = buffer.Length; |
1676 | response.ContentEncoding = Encoding.UTF8; | 1804 | response.ContentEncoding = Encoding.UTF8; |
1677 | 1805 | ||
1806 | |||
1678 | return buffer; | 1807 | return buffer; |
1679 | } | 1808 | } |
1680 | 1809 | ||
@@ -1775,6 +1904,8 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
1775 | HTTPDRunning = false; | 1904 | HTTPDRunning = false; |
1776 | try | 1905 | try |
1777 | { | 1906 | { |
1907 | // m_PollServiceManager.Stop(); | ||
1908 | |||
1778 | m_httpListener2.ExceptionThrown -= httpServerException; | 1909 | m_httpListener2.ExceptionThrown -= httpServerException; |
1779 | //m_httpListener2.DisconnectHandler = null; | 1910 | //m_httpListener2.DisconnectHandler = null; |
1780 | 1911 | ||
@@ -1840,6 +1971,12 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
1840 | m_rpcHandlers.Remove(method); | 1971 | m_rpcHandlers.Remove(method); |
1841 | } | 1972 | } |
1842 | 1973 | ||
1974 | public void RemoveJsonRPCHandler(string method) | ||
1975 | { | ||
1976 | lock(jsonRpcHandlers) | ||
1977 | jsonRpcHandlers.Remove(method); | ||
1978 | } | ||
1979 | |||
1843 | public bool RemoveLLSDHandler(string path, LLSDMethod handler) | 1980 | public bool RemoveLLSDHandler(string path, LLSDMethod handler) |
1844 | { | 1981 | { |
1845 | lock (m_llsdHandlers) | 1982 | lock (m_llsdHandlers) |