aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Servers
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/Servers')
-rw-r--r--OpenSim/Framework/Servers/BaseOpenSimServer.cs122
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs163
-rw-r--r--OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs2
-rw-r--r--OpenSim/Framework/Servers/HttpServer/JsonRPCMethod.cs34
-rw-r--r--OpenSim/Framework/Servers/HttpServer/JsonRpcResponse.cs150
-rw-r--r--OpenSim/Framework/Servers/MainServer.cs4
-rw-r--r--OpenSim/Framework/Servers/ServerBase.cs111
-rw-r--r--OpenSim/Framework/Servers/Tests/OSHttpTests.cs3
-rw-r--r--OpenSim/Framework/Servers/Tests/VersionInfoTests.cs3
9 files changed, 415 insertions, 177 deletions
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
index 2c21800..cb47cbf 100644
--- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs
+++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
@@ -27,7 +27,6 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics;
31using System.IO; 30using System.IO;
32using System.Reflection; 31using System.Reflection;
33using System.Text; 32using System.Text;
@@ -99,34 +98,6 @@ namespace OpenSim.Framework.Servers
99 m_console.Commands.AddCommand("General", false, "shutdown", 98 m_console.Commands.AddCommand("General", false, "shutdown",
100 "shutdown", 99 "shutdown",
101 "Quit the application", HandleQuit); 100 "Quit the application", HandleQuit);
102
103 m_console.Commands.AddCommand("General", false, "show threads",
104 "show threads",
105 "Show thread status", HandleShow);
106
107 m_console.Commands.AddCommand("General", false, "show version",
108 "show version",
109 "Show server version", HandleShow);
110
111 m_console.Commands.AddCommand("General", false, "threads abort",
112 "threads abort <thread-id>",
113 "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort);
114
115 m_console.Commands.AddCommand("General", false, "threads show",
116 "threads show",
117 "Show thread status. Synonym for \"show threads\"",
118 (string module, string[] args) => Notice(GetThreadsReport()));
119
120 m_console.Commands.AddCommand("General", false, "force gc",
121 "force gc",
122 "Manually invoke runtime garbage collection. For debugging purposes",
123 HandleForceGc);
124 }
125
126 private void HandleForceGc(string module, string[] args)
127 {
128 MainConsole.Instance.Output("Manually invoking runtime garbage collection");
129 GC.Collect();
130 } 101 }
131 102
132 /// <summary> 103 /// <summary>
@@ -159,54 +130,6 @@ namespace OpenSim.Framework.Servers
159 } 130 }
160 131
161 /// <summary> 132 /// <summary>
162 /// Get a report about the registered threads in this server.
163 /// </summary>
164 protected string GetThreadsReport()
165 {
166 // This should be a constant field.
167 string reportFormat = "{0,6} {1,35} {2,16} {3,13} {4,10} {5,30}";
168
169 StringBuilder sb = new StringBuilder();
170 Watchdog.ThreadWatchdogInfo[] threads = Watchdog.GetThreadsInfo();
171
172 sb.Append(threads.Length + " threads are being tracked:" + Environment.NewLine);
173
174 int timeNow = Environment.TickCount & Int32.MaxValue;
175
176 sb.AppendFormat(reportFormat, "ID", "NAME", "LAST UPDATE (MS)", "LIFETIME (MS)", "PRIORITY", "STATE");
177 sb.Append(Environment.NewLine);
178
179 foreach (Watchdog.ThreadWatchdogInfo twi in threads)
180 {
181 Thread t = twi.Thread;
182
183 sb.AppendFormat(
184 reportFormat,
185 t.ManagedThreadId,
186 t.Name,
187 timeNow - twi.LastTick,
188 timeNow - twi.FirstTick,
189 t.Priority,
190 t.ThreadState);
191
192 sb.Append("\n");
193 }
194
195 sb.Append("\n");
196
197 // For some reason mono 2.6.7 returns an empty threads set! Not going to confuse people by reporting
198 // zero active threads.
199 int totalThreads = Process.GetCurrentProcess().Threads.Count;
200 if (totalThreads > 0)
201 sb.AppendFormat("Total threads active: {0}\n\n", totalThreads);
202
203 sb.Append("Main threadpool (excluding script engine pools)\n");
204 sb.Append(Util.GetThreadPoolReport());
205
206 return sb.ToString();
207 }
208
209 /// <summary>
210 /// Performs initialisation of the scene, such as loading configuration from disk. 133 /// Performs initialisation of the scene, such as loading configuration from disk.
211 /// </summary> 134 /// </summary>
212 public virtual void Startup() 135 public virtual void Startup()
@@ -246,50 +169,7 @@ namespace OpenSim.Framework.Servers
246 private void HandleQuit(string module, string[] args) 169 private void HandleQuit(string module, string[] args)
247 { 170 {
248 Shutdown(); 171 Shutdown();
249 } 172 }
250
251 public override void HandleShow(string module, string[] cmd)
252 {
253 base.HandleShow(module, cmd);
254
255 List<string> args = new List<string>(cmd);
256
257 args.RemoveAt(0);
258
259 string[] showParams = args.ToArray();
260
261 switch (showParams[0])
262 {
263 case "threads":
264 Notice(GetThreadsReport());
265 break;
266
267 case "version":
268 Notice(GetVersionText());
269 break;
270 }
271 }
272
273 public virtual void HandleThreadsAbort(string module, string[] cmd)
274 {
275 if (cmd.Length != 3)
276 {
277 MainConsole.Instance.Output("Usage: threads abort <thread-id>");
278 return;
279 }
280
281 int threadId;
282 if (!int.TryParse(cmd[2], out threadId))
283 {
284 MainConsole.Instance.Output("ERROR: Thread id must be an integer");
285 return;
286 }
287
288 if (Watchdog.AbortThread(threadId))
289 MainConsole.Instance.OutputFormat("Aborted thread with id {0}", threadId);
290 else
291 MainConsole.Instance.OutputFormat("ERROR - Thread with id {0} not found in managed threads", threadId);
292 }
293 173
294 public string osSecret { 174 public string osSecret {
295 // Secret uuid for the simulator 175 // Secret uuid for the simulator
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index 77fce9e..bfbc480 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -77,6 +77,7 @@ namespace OpenSim.Framework.Servers.HttpServer
77 // protected HttpListener m_httpListener; 77 // protected HttpListener m_httpListener;
78 protected CoolHTTPListener m_httpListener2; 78 protected CoolHTTPListener m_httpListener2;
79 protected Dictionary<string, XmlRpcMethod> m_rpcHandlers = new Dictionary<string, XmlRpcMethod>(); 79 protected Dictionary<string, XmlRpcMethod> m_rpcHandlers = new Dictionary<string, XmlRpcMethod>();
80 protected Dictionary<string, JsonRPCMethod> jsonRpcHandlers = new Dictionary<string, JsonRPCMethod>();
80 protected Dictionary<string, bool> m_rpcHandlersKeepAlive = new Dictionary<string, bool>(); 81 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/ 82 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>(); 83 protected Dictionary<string, LLSDMethod> m_llsdHandlers = new Dictionary<string, LLSDMethod>();
@@ -217,6 +218,37 @@ namespace OpenSim.Framework.Servers.HttpServer
217 return new List<string>(m_rpcHandlers.Keys); 218 return new List<string>(m_rpcHandlers.Keys);
218 } 219 }
219 220
221 // JsonRPC
222 public bool AddJsonRPCHandler(string method, JsonRPCMethod handler)
223 {
224 lock(jsonRpcHandlers)
225 {
226 jsonRpcHandlers.Add(method, handler);
227 }
228 return true;
229 }
230
231 public JsonRPCMethod GetJsonRPCHandler(string method)
232 {
233 lock (jsonRpcHandlers)
234 {
235 if (jsonRpcHandlers.ContainsKey(method))
236 {
237 return jsonRpcHandlers[method];
238 }
239 else
240 {
241 return null;
242 }
243 }
244 }
245
246 public List<string> GetJsonRpcHandlerKeys()
247 {
248 lock (jsonRpcHandlers)
249 return new List<string>(jsonRpcHandlers.Keys);
250 }
251
220 public bool AddHTTPHandler(string methodName, GenericHTTPMethod handler) 252 public bool AddHTTPHandler(string methodName, GenericHTTPMethod handler)
221 { 253 {
222 //m_log.DebugFormat("[BASE HTTP SERVER]: Registering {0}", methodName); 254 //m_log.DebugFormat("[BASE HTTP SERVER]: Registering {0}", methodName);
@@ -437,7 +469,7 @@ namespace OpenSim.Framework.Servers.HttpServer
437// reqnum = String.Format("{0}:{1}",request.RemoteIPEndPoint,request.Headers["opensim-request-id"]); 469// 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); 470 //m_log.DebugFormat("[BASE HTTP SERVER]: <{0}> handle request for {1}",reqnum,request.RawUrl);
439 471
440 Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true); 472 Culture.SetCurrentCulture();
441 473
442// // This is the REST agent interface. We require an agent to properly identify 474// // 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 475// // itself. If the REST handler recognizes the prefix it will attempt to
@@ -557,10 +589,18 @@ namespace OpenSim.Framework.Servers.HttpServer
557 589
558 buffer = HandleLLSDRequests(request, response); 590 buffer = HandleLLSDRequests(request, response);
559 break; 591 break;
592
593 case "application/json-rpc":
594 if (DebugLevel >= 3)
595 LogIncomingToContentTypeHandler(request);
596
597 buffer = HandleJsonRpcRequests(request, response);
598 break;
560 599
561 case "text/xml": 600 case "text/xml":
562 case "application/xml": 601 case "application/xml":
563 case "application/json": 602 case "application/json":
603
564 default: 604 default:
565 //m_log.Info("[Debug BASE HTTP SERVER]: in default handler"); 605 //m_log.Info("[Debug BASE HTTP SERVER]: in default handler");
566 // Point of note.. the DoWeHaveA methods check for an EXACT path 606 // Point of note.. the DoWeHaveA methods check for an EXACT path
@@ -986,6 +1026,74 @@ namespace OpenSim.Framework.Servers.HttpServer
986 return buffer; 1026 return buffer;
987 } 1027 }
988 1028
1029 // JsonRpc (v2.0 only)
1030 private byte[] HandleJsonRpcRequests(OSHttpRequest request, OSHttpResponse response)
1031 {
1032 Stream requestStream = request.InputStream;
1033 JsonRpcResponse jsonRpcResponse = new JsonRpcResponse();
1034 OSDMap jsonRpcRequest = null;
1035
1036 try
1037 {
1038 jsonRpcRequest = (OSDMap)OSDParser.DeserializeJson(requestStream);
1039 }
1040 catch (LitJson.JsonException e)
1041 {
1042 jsonRpcResponse.Error.Code = ErrorCode.InternalError;
1043 jsonRpcResponse.Error.Message = e.Message;
1044 }
1045
1046 requestStream.Close();
1047
1048 if (jsonRpcRequest != null)
1049 {
1050 if (jsonRpcRequest.ContainsKey("jsonrpc") || jsonRpcRequest["jsonrpc"].AsString() == "2.0")
1051 {
1052 jsonRpcResponse.JsonRpc = "2.0";
1053
1054 // If we have no id, then it's a "notification"
1055 if (jsonRpcRequest.ContainsKey("id"))
1056 {
1057 jsonRpcResponse.Id = jsonRpcRequest["id"].AsString();
1058 }
1059
1060 string methodname = jsonRpcRequest["method"];
1061 JsonRPCMethod method;
1062
1063 if (jsonRpcHandlers.ContainsKey(methodname))
1064 {
1065 lock(jsonRpcHandlers)
1066 {
1067 jsonRpcHandlers.TryGetValue(methodname, out method);
1068 }
1069
1070 method(jsonRpcRequest, ref jsonRpcResponse);
1071 }
1072 else // Error no hanlder defined for requested method
1073 {
1074 jsonRpcResponse.Error.Code = ErrorCode.InvalidRequest;
1075 jsonRpcResponse.Error.Message = string.Format ("No handler defined for {0}", methodname);
1076 }
1077 }
1078 else // not json-rpc 2.0 could be v1
1079 {
1080 jsonRpcResponse.Error.Code = ErrorCode.InvalidRequest;
1081 jsonRpcResponse.Error.Message = "Must be valid json-rpc 2.0 see: http://www.jsonrpc.org/specification";
1082
1083 if (jsonRpcRequest.ContainsKey("id"))
1084 jsonRpcResponse.Id = jsonRpcRequest["id"].AsString();
1085 }
1086 }
1087
1088 response.KeepAlive = true;
1089 string responseData = string.Empty;
1090
1091 responseData = jsonRpcResponse.Serialize();
1092
1093 byte[] buffer = Encoding.UTF8.GetBytes(responseData);
1094 return buffer;
1095 }
1096
989 private byte[] HandleLLSDRequests(OSHttpRequest request, OSHttpResponse response) 1097 private byte[] HandleLLSDRequests(OSHttpRequest request, OSHttpResponse response)
990 { 1098 {
991 //m_log.Warn("[BASE HTTP SERVER]: We've figured out it's a LLSD Request"); 1099 //m_log.Warn("[BASE HTTP SERVER]: We've figured out it's a LLSD Request");
@@ -1283,59 +1391,6 @@ namespace OpenSim.Framework.Servers.HttpServer
1283 map["login"] = OSD.FromString("false"); 1391 map["login"] = OSD.FromString("false");
1284 return map; 1392 return map;
1285 } 1393 }
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 1394
1340 public byte[] HandleHTTPRequest(OSHttpRequest request, OSHttpResponse response) 1395 public byte[] HandleHTTPRequest(OSHttpRequest request, OSHttpResponse response)
1341 { 1396 {
diff --git a/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs
index 0bd3aae..13b5dd3 100644
--- a/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs
@@ -97,6 +97,8 @@ namespace OpenSim.Framework.Servers.HttpServer
97 bool AddXmlRPCHandler(string method, XmlRpcMethod handler); 97 bool AddXmlRPCHandler(string method, XmlRpcMethod handler);
98 bool AddXmlRPCHandler(string method, XmlRpcMethod handler, bool keepAlive); 98 bool AddXmlRPCHandler(string method, XmlRpcMethod handler, bool keepAlive);
99 99
100 bool AddJsonRPCHandler(string method, JsonRPCMethod handler);
101
100 /// <summary> 102 /// <summary>
101 /// Gets the XML RPC handler for given method name 103 /// Gets the XML RPC handler for given method name
102 /// </summary> 104 /// </summary>
diff --git a/OpenSim/Framework/Servers/HttpServer/JsonRPCMethod.cs b/OpenSim/Framework/Servers/HttpServer/JsonRPCMethod.cs
new file mode 100644
index 0000000..7334049
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/JsonRPCMethod.cs
@@ -0,0 +1,34 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System.Net;
29using OpenMetaverse.StructuredData;
30
31namespace OpenSim.Framework.Servers.HttpServer
32{
33 public delegate void JsonRPCMethod(OSDMap jsonRpcRequest, ref JsonRpcResponse response);
34}
diff --git a/OpenSim/Framework/Servers/HttpServer/JsonRpcResponse.cs b/OpenSim/Framework/Servers/HttpServer/JsonRpcResponse.cs
new file mode 100644
index 0000000..2c50587
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/JsonRpcResponse.cs
@@ -0,0 +1,150 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Net;
29using OpenMetaverse.StructuredData;
30
31namespace OpenSim.Framework.Servers.HttpServer
32{
33 public sealed class ErrorCode
34 {
35 private ErrorCode() {}
36
37 public const int ParseError = -32700;
38 public const int InvalidRequest = -32600;
39 public const int MethodNotFound = -32601;
40 public const int InvalidParams = -32602;
41 public const int InternalError = -32604;
42
43 }
44
45 public class JsonRpcError
46 {
47 internal OSDMap Error = new OSDMap();
48
49 public int Code
50 {
51 get
52 {
53 if (Error.ContainsKey("code"))
54 return Error["code"].AsInteger();
55 else
56 return 0;
57 }
58 set
59 {
60 Error["code"] = OSD.FromInteger(value);
61 }
62 }
63
64 public string Message
65 {
66 get
67 {
68 if (Error.ContainsKey("message"))
69 return Error["message"].AsString();
70 else
71 return null;
72 }
73 set
74 {
75 Error["message"] = OSD.FromString(value);
76 }
77 }
78
79 public OSD Data
80 {
81 get; set;
82 }
83 }
84
85 public class JsonRpcResponse
86 {
87 public string JsonRpc
88 {
89 get
90 {
91 return Reply["jsonrpc"].AsString();
92 }
93 set
94 {
95 Reply["jsonrpc"] = OSD.FromString(value);
96 }
97 }
98
99 public string Id
100 {
101 get
102 {
103 return Reply["id"].AsString();
104 }
105 set
106 {
107 Reply["id"] = OSD.FromString(value);
108 }
109 }
110
111 public OSD Result
112 {
113 get; set;
114 }
115
116 public JsonRpcError Error
117 {
118 get; set;
119 }
120
121 public OSDMap Reply = new OSDMap();
122
123 public JsonRpcResponse()
124 {
125 Error = new JsonRpcError();
126 }
127
128 public string Serialize()
129 {
130 if (Result != null)
131 Reply["result"] = Result;
132
133 if (Error.Code != 0)
134 {
135 Reply["error"] = (OSD)Error.Error;
136 }
137
138 string result = string.Empty;
139 try
140 {
141 result = OSDParser.SerializeJsonString(Reply);
142 }
143 catch
144 {
145
146 }
147 return result;
148 }
149 }
150}
diff --git a/OpenSim/Framework/Servers/MainServer.cs b/OpenSim/Framework/Servers/MainServer.cs
index ae7d515..293887f 100644
--- a/OpenSim/Framework/Servers/MainServer.cs
+++ b/OpenSim/Framework/Servers/MainServer.cs
@@ -230,6 +230,10 @@ namespace OpenSim.Framework.Servers
230 List<String> poll = httpServer.GetPollServiceHandlerKeys(); 230 List<String> poll = httpServer.GetPollServiceHandlerKeys();
231 foreach (String s in httpServer.GetHTTPHandlerKeys()) 231 foreach (String s in httpServer.GetHTTPHandlerKeys())
232 handlers.AppendFormat("\t{0} {1}\n", s, (poll.Contains(s) ? "(poll service)" : string.Empty)); 232 handlers.AppendFormat("\t{0} {1}\n", s, (poll.Contains(s) ? "(poll service)" : string.Empty));
233
234 handlers.AppendFormat("* JSONRPC:\n");
235 foreach (String s in httpServer.GetJsonRpcHandlerKeys())
236 handlers.AppendFormat("\t{0}\n", s);
233 237
234// handlers.AppendFormat("* Agent:\n"); 238// handlers.AppendFormat("* Agent:\n");
235// foreach (String s in httpServer.GetAgentHandlerKeys()) 239// foreach (String s in httpServer.GetAgentHandlerKeys())
diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs
index c182a3a..47baac8 100644
--- a/OpenSim/Framework/Servers/ServerBase.cs
+++ b/OpenSim/Framework/Servers/ServerBase.cs
@@ -27,16 +27,19 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics;
30using System.IO; 31using System.IO;
31using System.Reflection; 32using System.Reflection;
32using System.Text; 33using System.Text;
33using System.Text.RegularExpressions; 34using System.Text.RegularExpressions;
35using System.Threading;
34using log4net; 36using log4net;
35using log4net.Appender; 37using log4net.Appender;
36using log4net.Core; 38using log4net.Core;
37using log4net.Repository; 39using log4net.Repository;
38using Nini.Config; 40using Nini.Config;
39using OpenSim.Framework.Console; 41using OpenSim.Framework.Console;
42using OpenSim.Framework.Monitoring;
40 43
41namespace OpenSim.Framework.Servers 44namespace OpenSim.Framework.Servers
42{ 45{
@@ -168,6 +171,9 @@ namespace OpenSim.Framework.Servers
168 "General", false, "show info", "show info", "Show general information about the server", HandleShow); 171 "General", false, "show info", "show info", "Show general information about the server", HandleShow);
169 172
170 m_console.Commands.AddCommand( 173 m_console.Commands.AddCommand(
174 "General", false, "show version", "show version", "Show server version", HandleShow);
175
176 m_console.Commands.AddCommand(
171 "General", false, "show uptime", "show uptime", "Show server uptime", HandleShow); 177 "General", false, "show uptime", "show uptime", "Show server uptime", HandleShow);
172 178
173 m_console.Commands.AddCommand( 179 m_console.Commands.AddCommand(
@@ -206,6 +212,34 @@ namespace OpenSim.Framework.Servers
206 "General", false, "command-script", 212 "General", false, "command-script",
207 "command-script <script>", 213 "command-script <script>",
208 "Run a command script from file", HandleScript); 214 "Run a command script from file", HandleScript);
215
216 m_console.Commands.AddCommand(
217 "General", false, "show threads",
218 "show threads",
219 "Show thread status", HandleShow);
220
221 m_console.Commands.AddCommand(
222 "General", false, "threads abort",
223 "threads abort <thread-id>",
224 "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort);
225
226 m_console.Commands.AddCommand(
227 "General", false, "threads show",
228 "threads show",
229 "Show thread status. Synonym for \"show threads\"",
230 (string module, string[] args) => Notice(GetThreadsReport()));
231
232 m_console.Commands.AddCommand(
233 "General", false, "force gc",
234 "force gc",
235 "Manually invoke runtime garbage collection. For debugging purposes",
236 HandleForceGc);
237 }
238
239 private void HandleForceGc(string module, string[] args)
240 {
241 Notice("Manually invoking runtime garbage collection");
242 GC.Collect();
209 } 243 }
210 244
211 public virtual void HandleShow(string module, string[] cmd) 245 public virtual void HandleShow(string module, string[] cmd)
@@ -222,9 +256,17 @@ namespace OpenSim.Framework.Servers
222 ShowInfo(); 256 ShowInfo();
223 break; 257 break;
224 258
259 case "version":
260 Notice(GetVersionText());
261 break;
262
225 case "uptime": 263 case "uptime":
226 Notice(GetUptimeReport()); 264 Notice(GetUptimeReport());
227 break; 265 break;
266
267 case "threads":
268 Notice(GetThreadsReport());
269 break;
228 } 270 }
229 } 271 }
230 272
@@ -537,6 +579,75 @@ namespace OpenSim.Framework.Servers
537 } 579 }
538 580
539 /// <summary> 581 /// <summary>
582 /// Get a report about the registered threads in this server.
583 /// </summary>
584 protected string GetThreadsReport()
585 {
586 // This should be a constant field.
587 string reportFormat = "{0,6} {1,35} {2,16} {3,13} {4,10} {5,30}";
588
589 StringBuilder sb = new StringBuilder();
590 Watchdog.ThreadWatchdogInfo[] threads = Watchdog.GetThreadsInfo();
591
592 sb.Append(threads.Length + " threads are being tracked:" + Environment.NewLine);
593
594 int timeNow = Environment.TickCount & Int32.MaxValue;
595
596 sb.AppendFormat(reportFormat, "ID", "NAME", "LAST UPDATE (MS)", "LIFETIME (MS)", "PRIORITY", "STATE");
597 sb.Append(Environment.NewLine);
598
599 foreach (Watchdog.ThreadWatchdogInfo twi in threads)
600 {
601 Thread t = twi.Thread;
602
603 sb.AppendFormat(
604 reportFormat,
605 t.ManagedThreadId,
606 t.Name,
607 timeNow - twi.LastTick,
608 timeNow - twi.FirstTick,
609 t.Priority,
610 t.ThreadState);
611
612 sb.Append("\n");
613 }
614
615 sb.Append("\n");
616
617 // For some reason mono 2.6.7 returns an empty threads set! Not going to confuse people by reporting
618 // zero active threads.
619 int totalThreads = Process.GetCurrentProcess().Threads.Count;
620 if (totalThreads > 0)
621 sb.AppendFormat("Total threads active: {0}\n\n", totalThreads);
622
623 sb.Append("Main threadpool (excluding script engine pools)\n");
624 sb.Append(Util.GetThreadPoolReport());
625
626 return sb.ToString();
627 }
628
629 public virtual void HandleThreadsAbort(string module, string[] cmd)
630 {
631 if (cmd.Length != 3)
632 {
633 MainConsole.Instance.Output("Usage: threads abort <thread-id>");
634 return;
635 }
636
637 int threadId;
638 if (!int.TryParse(cmd[2], out threadId))
639 {
640 MainConsole.Instance.Output("ERROR: Thread id must be an integer");
641 return;
642 }
643
644 if (Watchdog.AbortThread(threadId))
645 MainConsole.Instance.OutputFormat("Aborted thread with id {0}", threadId);
646 else
647 MainConsole.Instance.OutputFormat("ERROR - Thread with id {0} not found in managed threads", threadId);
648 }
649
650 /// <summary>
540 /// Console output is only possible if a console has been established. 651 /// Console output is only possible if a console has been established.
541 /// That is something that cannot be determined within this class. So 652 /// That is something that cannot be determined within this class. So
542 /// all attempts to use the console MUST be verified. 653 /// all attempts to use the console MUST be verified.
diff --git a/OpenSim/Framework/Servers/Tests/OSHttpTests.cs b/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
index 4c2f586..50f306e 100644
--- a/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
+++ b/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
@@ -35,11 +35,12 @@ using HttpServer;
35using HttpServer.FormDecoders; 35using HttpServer.FormDecoders;
36using NUnit.Framework; 36using NUnit.Framework;
37using OpenSim.Framework.Servers.HttpServer; 37using OpenSim.Framework.Servers.HttpServer;
38using OpenSim.Tests.Common;
38 39
39namespace OpenSim.Framework.Servers.Tests 40namespace OpenSim.Framework.Servers.Tests
40{ 41{
41 [TestFixture] 42 [TestFixture]
42 public class OSHttpTests 43 public class OSHttpTests : OpenSimTestCase
43 { 44 {
44 // we need an IHttpClientContext for our tests 45 // we need an IHttpClientContext for our tests
45 public class TestHttpClientContext: IHttpClientContext 46 public class TestHttpClientContext: IHttpClientContext
diff --git a/OpenSim/Framework/Servers/Tests/VersionInfoTests.cs b/OpenSim/Framework/Servers/Tests/VersionInfoTests.cs
index 49e5061..480f2bb 100644
--- a/OpenSim/Framework/Servers/Tests/VersionInfoTests.cs
+++ b/OpenSim/Framework/Servers/Tests/VersionInfoTests.cs
@@ -29,11 +29,12 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Text; 30using System.Text;
31using NUnit.Framework; 31using NUnit.Framework;
32using OpenSim.Tests.Common;
32 33
33namespace OpenSim.Framework.Servers.Tests 34namespace OpenSim.Framework.Servers.Tests
34{ 35{
35 [TestFixture] 36 [TestFixture]
36 public class VersionInfoTests 37 public class VersionInfoTests : OpenSimTestCase
37 { 38 {
38 [Test] 39 [Test]
39 public void TestVersionLength() 40 public void TestVersionLength()