aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Console/RemoteConsole.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/Console/RemoteConsole.cs')
-rw-r--r--OpenSim/Framework/Console/RemoteConsole.cs358
1 files changed, 348 insertions, 10 deletions
diff --git a/OpenSim/Framework/Console/RemoteConsole.cs b/OpenSim/Framework/Console/RemoteConsole.cs
index 73209be..da8556a 100644
--- a/OpenSim/Framework/Console/RemoteConsole.cs
+++ b/OpenSim/Framework/Console/RemoteConsole.cs
@@ -26,30 +26,43 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Xml;
30using System.Collections;
29using System.Collections.Generic; 31using System.Collections.Generic;
30using System.Diagnostics; 32using System.Diagnostics;
31using System.Reflection; 33using System.Reflection;
32using System.Text; 34using System.Text;
33using System.Threading; 35using System.Threading;
36using OpenMetaverse;
34using Nini.Config; 37using Nini.Config;
35using OpenSim.Framework.Servers.HttpServer; 38using OpenSim.Framework.Servers.HttpServer;
36using log4net; 39using log4net;
37 40
38namespace OpenSim.Framework.Console 41namespace OpenSim.Framework.Console
39{ 42{
43 public class ConsoleConnection
44 {
45 public int last;
46 public long lastLineSeen;
47 }
48
40 // A console that uses REST interfaces 49 // A console that uses REST interfaces
41 // 50 //
42 public class RemoteConsole : CommandConsole 51 public class RemoteConsole : CommandConsole
43 { 52 {
44// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 54
46 // private IHttpServer m_Server = null; 55 private IHttpServer m_Server = null;
47 // private IConfigSource m_Config = null; 56 private IConfigSource m_Config = null;
48 57
49 private List<string> m_Scrollback = new List<string>(); 58 private List<string> m_Scrollback = new List<string>();
50 private ManualResetEvent m_DataEvent = new ManualResetEvent(false); 59 private ManualResetEvent m_DataEvent = new ManualResetEvent(false);
51 private List<string> m_InputData = new List<string>(); 60 private List<string> m_InputData = new List<string>();
52 private uint m_LineNumber = 1; 61 private long m_LineNumber = 0;
62 private Dictionary<UUID, ConsoleConnection> m_Connections =
63 new Dictionary<UUID, ConsoleConnection>();
64 private string m_UserName = String.Empty;
65 private string m_Password = String.Empty;
53 66
54 public RemoteConsole(string defaultPrompt) : base(defaultPrompt) 67 public RemoteConsole(string defaultPrompt) : base(defaultPrompt)
55 { 68 {
@@ -57,12 +70,23 @@ namespace OpenSim.Framework.Console
57 70
58 public void ReadConfig(IConfigSource config) 71 public void ReadConfig(IConfigSource config)
59 { 72 {
60 // m_Config = config; 73 m_Config = config;
74
75 IConfig netConfig = m_Config.Configs["Network"];
76 if (netConfig == null)
77 return;
78
79 m_UserName = netConfig.GetString("ConsoleUser", String.Empty);
80 m_Password = netConfig.GetString("ConsolePass", String.Empty);
61 } 81 }
62 82
63 public void SetServer(IHttpServer server) 83 public void SetServer(IHttpServer server)
64 { 84 {
65 // m_Server = server; 85 m_Server = server;
86
87 m_Server.AddHTTPHandler("/StartSession/", HandleHttpStartSession);
88 m_Server.AddHTTPHandler("/CloseSession/", HandleHttpCloseSession);
89 m_Server.AddHTTPHandler("/SessionCommand/", HandleHttpSessionCommand);
66 } 90 }
67 91
68 public override void Output(string text, string level) 92 public override void Output(string text, string level)
@@ -71,16 +95,19 @@ namespace OpenSim.Framework.Console
71 { 95 {
72 while (m_Scrollback.Count >= 1000) 96 while (m_Scrollback.Count >= 1000)
73 m_Scrollback.RemoveAt(0); 97 m_Scrollback.RemoveAt(0);
74 m_Scrollback.Add(String.Format("{0}", m_LineNumber)+":"+level+":"+text);
75 m_LineNumber++; 98 m_LineNumber++;
99 m_Scrollback.Add(String.Format("{0}", m_LineNumber)+":"+level+":"+text);
76 } 100 }
77 System.Console.Write(text); 101 System.Console.WriteLine(text.Trim());
102 }
103
104 public override void Output(string text)
105 {
106 Output(text, "normal");
78 } 107 }
79 108
80 public override string ReadLine(string p, bool isCommand, bool e) 109 public override string ReadLine(string p, bool isCommand, bool e)
81 { 110 {
82 System.Console.Write("{0}", prompt);
83
84 m_DataEvent.WaitOne(); 111 m_DataEvent.WaitOne();
85 112
86 lock (m_InputData) 113 lock (m_InputData)
@@ -115,5 +142,316 @@ namespace OpenSim.Framework.Console
115 return cmdinput; 142 return cmdinput;
116 } 143 }
117 } 144 }
145
146 private void DoExpire()
147 {
148 List<UUID> expired = new List<UUID>();
149
150 lock (m_Connections)
151 {
152 foreach (KeyValuePair<UUID, ConsoleConnection> kvp in m_Connections)
153 {
154 if (System.Environment.TickCount - kvp.Value.last > 500000)
155 expired.Add(kvp.Key);
156 }
157
158 foreach (UUID id in expired)
159 {
160 m_Connections.Remove(id);
161 CloseConnection(id);
162 }
163 }
164 }
165
166 private Hashtable HandleHttpStartSession(Hashtable request)
167 {
168 DoExpire();
169
170 Hashtable post = DecodePostString(request["body"].ToString());
171 Hashtable reply = new Hashtable();
172
173 reply["str_response_string"] = "";
174 reply["int_response_code"] = 401;
175 reply["content_type"] = "text/plain";
176
177 if (m_UserName == String.Empty)
178 return reply;
179
180 if (post["USER"] == null || post["PASS"] == null)
181 return reply;
182
183 if (m_UserName != post["USER"].ToString() ||
184 m_Password != post["PASS"].ToString())
185 {
186 return reply;
187 }
188
189 ConsoleConnection c = new ConsoleConnection();
190 c.last = System.Environment.TickCount;
191 c.lastLineSeen = 0;
192
193 UUID sessionID = UUID.Random();
194
195 lock (m_Connections)
196 {
197 m_Connections[sessionID] = c;
198 }
199
200 string uri = "/ReadResponses/" + sessionID.ToString() + "/";
201
202 m_Server.AddPollServiceHTTPHandler(uri, HandleHttpCloseSession,
203 new PollServiceEventArgs(HasEvents, GetEvents, NoEvents,
204 sessionID));
205
206 XmlDocument xmldoc = new XmlDocument();
207 XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
208 "", "");
209
210 xmldoc.AppendChild(xmlnode);
211 XmlElement rootElement = xmldoc.CreateElement("", "ConsoleSession",
212 "");
213
214 xmldoc.AppendChild(rootElement);
215
216 XmlElement id = xmldoc.CreateElement("", "SessionID", "");
217 id.AppendChild(xmldoc.CreateTextNode(sessionID.ToString()));
218
219 rootElement.AppendChild(id);
220 rootElement.AppendChild(MainConsole.Instance.Commands.GetXml(xmldoc));
221
222 reply["str_response_string"] = xmldoc.InnerXml;
223 reply["int_response_code"] = 200;
224 reply["content_type"] = "text/xml";
225
226 return reply;
227 }
228
229 private Hashtable HandleHttpCloseSession(Hashtable request)
230 {
231 DoExpire();
232
233 Hashtable post = DecodePostString(request["body"].ToString());
234 Hashtable reply = new Hashtable();
235
236 reply["str_response_string"] = "";
237 reply["int_response_code"] = 404;
238 reply["content_type"] = "text/plain";
239
240 if (post["ID"] == null)
241 return reply;
242
243 UUID id;
244 if (!UUID.TryParse(post["ID"].ToString(), out id))
245 return reply;
246
247 lock (m_Connections)
248 {
249 if (m_Connections.ContainsKey(id))
250 {
251 m_Connections.Remove(id);
252 CloseConnection(id);
253 }
254 }
255
256 XmlDocument xmldoc = new XmlDocument();
257 XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
258 "", "");
259
260 xmldoc.AppendChild(xmlnode);
261 XmlElement rootElement = xmldoc.CreateElement("", "ConsoleSession",
262 "");
263
264 xmldoc.AppendChild(rootElement);
265
266 XmlElement res = xmldoc.CreateElement("", "Result", "");
267 res.AppendChild(xmldoc.CreateTextNode("OK"));
268
269 rootElement.AppendChild(res);
270
271 reply["str_response_string"] = xmldoc.InnerXml;
272 reply["int_response_code"] = 200;
273 reply["content_type"] = "text/plain";
274
275 return reply;
276 }
277
278 private Hashtable HandleHttpSessionCommand(Hashtable request)
279 {
280 DoExpire();
281
282 Hashtable post = DecodePostString(request["body"].ToString());
283 Hashtable reply = new Hashtable();
284
285 reply["str_response_string"] = "";
286 reply["int_response_code"] = 404;
287 reply["content_type"] = "text/plain";
288
289 if (post["ID"] == null)
290 return reply;
291
292 UUID id;
293 if (!UUID.TryParse(post["ID"].ToString(), out id))
294 return reply;
295
296 if (post["COMMAND"] == null || post["COMMAND"].ToString() == String.Empty)
297 return reply;
298
299 lock (m_InputData)
300 {
301 m_DataEvent.Set();
302 m_InputData.Add(post["COMMAND"].ToString());
303 }
304
305 XmlDocument xmldoc = new XmlDocument();
306 XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
307 "", "");
308
309 xmldoc.AppendChild(xmlnode);
310 XmlElement rootElement = xmldoc.CreateElement("", "ConsoleSession",
311 "");
312
313 xmldoc.AppendChild(rootElement);
314
315 XmlElement res = xmldoc.CreateElement("", "Result", "");
316 res.AppendChild(xmldoc.CreateTextNode("OK"));
317
318 rootElement.AppendChild(res);
319
320 reply["str_response_string"] = xmldoc.InnerXml;
321 reply["int_response_code"] = 200;
322 reply["content_type"] = "text/plain";
323
324 return reply;
325 }
326
327 private Hashtable DecodePostString(string data)
328 {
329 Hashtable result = new Hashtable();
330
331 string[] terms = data.Split(new char[] {'&'});
332
333 foreach (string term in terms)
334 {
335 string[] elems = term.Split(new char[] {'='});
336 if (elems.Length == 0)
337 continue;
338
339 string name = System.Web.HttpUtility.UrlDecode(elems[0]);
340 string value = String.Empty;
341
342 if (elems.Length > 1)
343 value = System.Web.HttpUtility.UrlDecode(elems[1]);
344
345 result[name] = value;
346 }
347
348 return result;
349 }
350
351 public void CloseConnection(UUID id)
352 {
353 try
354 {
355 string uri = "/ReadResponses/" + id.ToString() + "/";
356
357 m_Server.RemovePollServiceHTTPHandler("", uri);
358 }
359 catch (Exception)
360 {
361 }
362 }
363
364 private bool HasEvents(UUID sessionID)
365 {
366 ConsoleConnection c = null;
367
368 lock (m_Connections)
369 {
370 if (!m_Connections.ContainsKey(sessionID))
371 return false;
372 c = m_Connections[sessionID];
373 }
374 c.last = System.Environment.TickCount;
375 if (c.lastLineSeen < m_LineNumber)
376 return true;
377 return false;
378 }
379
380 private Hashtable GetEvents(UUID sessionID, string request)
381 {
382 ConsoleConnection c = null;
383
384 lock (m_Connections)
385 {
386 if (!m_Connections.ContainsKey(sessionID))
387 return NoEvents();
388 c = m_Connections[sessionID];
389 }
390 c.last = System.Environment.TickCount;
391 if (c.lastLineSeen >= m_LineNumber)
392 return NoEvents();
393
394 Hashtable result = new Hashtable();
395
396 XmlDocument xmldoc = new XmlDocument();
397 XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
398 "", "");
399
400 xmldoc.AppendChild(xmlnode);
401 XmlElement rootElement = xmldoc.CreateElement("", "ConsoleSession",
402 "");
403
404 lock (m_Scrollback)
405 {
406 long startLine = m_LineNumber - m_Scrollback.Count;
407 long sendStart = startLine;
408 if (sendStart < c.lastLineSeen)
409 sendStart = c.lastLineSeen;
410
411 for (long i = sendStart ; i < m_LineNumber ; i++)
412 {
413 XmlElement res = xmldoc.CreateElement("", "Line", "");
414 long line = i + 1;
415 res.SetAttribute("Number", line.ToString());
416 res.AppendChild(xmldoc.CreateTextNode(m_Scrollback[(int)(i - startLine)]));
417
418 rootElement.AppendChild(res);
419 }
420 }
421 c.lastLineSeen = m_LineNumber;
422
423 xmldoc.AppendChild(rootElement);
424
425 result["str_response_string"] = xmldoc.InnerXml;
426 result["int_response_code"] = 200;
427 result["content_type"] = "application/xml";
428 result["keepalive"] = false;
429 result["reusecontext"] = false;
430
431 return result;
432 }
433
434 private Hashtable NoEvents()
435 {
436 Hashtable result = new Hashtable();
437
438 XmlDocument xmldoc = new XmlDocument();
439 XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
440 "", "");
441
442 xmldoc.AppendChild(xmlnode);
443 XmlElement rootElement = xmldoc.CreateElement("", "ConsoleSession",
444 "");
445
446 xmldoc.AppendChild(rootElement);
447
448 result["str_response_string"] = xmldoc.InnerXml;
449 result["int_response_code"] = 200;
450 result["content_type"] = "text/xml";
451 result["keepalive"] = false;
452 result["reusecontext"] = false;
453
454 return result;
455 }
118 } 456 }
119} 457}