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.cs253
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)