From 5d50a5a37cdca2a93d14ea1521d28af7bdb74161 Mon Sep 17 00:00:00 2001 From: Vorspire Date: Sun, 23 Aug 2015 01:34:04 +0100 Subject: [PATCH] + Added simple HttpListener for the integrated RunUO status page. * HttpListener will serve the status page to a URI in the format of http:///status/ * Port 80 may need to be white-listed for external requests to be served. --- Scripts/Misc/WebStatus.cs | 229 +++++++++++++++++++++++++------------- 1 file changed, 152 insertions(+), 77 deletions(-) diff --git a/Scripts/Misc/WebStatus.cs b/Scripts/Misc/WebStatus.cs index 4401d6728..7aac70469 100644 --- a/Scripts/Misc/WebStatus.cs +++ b/Scripts/Misc/WebStatus.cs @@ -1,118 +1,193 @@ +#region References using System; using System.IO; +using System.Linq; +using System.Net; using System.Text; -using Server; -using Server.Network; + using Server.Guilds; +using Server.Network; +#endregion namespace Server.Misc { public class StatusPage : Timer { - public static bool Enabled = false; + public static readonly bool Enabled = true; + + private static HttpListener _Listener; + + private static string _StatusPage = String.Empty; + private static byte[] _StatusBuffer = new byte[0]; + + private static readonly object _StatusLock = new object(); public static void Initialize() { - if ( Enabled ) - new StatusPage().Start(); + if (!Enabled) + { + return; + } + + new StatusPage().Start(); + + Listen(); } - public StatusPage() : base( TimeSpan.FromSeconds( 5.0 ), TimeSpan.FromSeconds( 60.0 ) ) + private static void Listen() { - Priority = TimerPriority.FiveSeconds; + if (!HttpListener.IsSupported) + { + return; + } + + if (_Listener == null) + { + _Listener = new HttpListener(); + _Listener.Prefixes.Add("http://*:80/status/"); + _Listener.Start(); + } + else if (!_Listener.IsListening) + { + _Listener.Start(); + } + + if (_Listener.IsListening) + { + _Listener.BeginGetContext(ListenerCallback, null); + } } - private static string Encode( string input ) + private static void ListenerCallback(IAsyncResult result) { - StringBuilder sb = new StringBuilder( input ); + try + { + var context = _Listener.EndGetContext(result); - sb.Replace( "&", "&" ); - sb.Replace( "<", "<" ); - sb.Replace( ">", ">" ); - sb.Replace( "\"", """ ); - sb.Replace( "'", "'" ); + byte[] buffer; + + lock (_StatusLock) + { + buffer = _StatusBuffer; + } + + context.Response.ContentLength64 = buffer.Length; + context.Response.OutputStream.Write(buffer, 0, buffer.Length); + context.Response.OutputStream.Close(); + } + catch + { } + + Listen(); + } + + private static string Encode(string input) + { + var sb = new StringBuilder(input); + + sb.Replace("&", "&"); + sb.Replace("<", "<"); + sb.Replace(">", ">"); + sb.Replace("\"", """); + sb.Replace("'", "'"); return sb.ToString(); } + public StatusPage() + : base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(60.0)) + { + Priority = TimerPriority.FiveSeconds; + } + protected override void OnTick() { - if ( !Directory.Exists( "web" ) ) - Directory.CreateDirectory( "web" ); - - using ( StreamWriter op = new StreamWriter( "web/status.html" ) ) + if (!Directory.Exists("web")) { - op.WriteLine( "" ); - op.WriteLine( " " ); - op.WriteLine( " RunUO Server Status"); - op.WriteLine( " " ); - op.WriteLine( " " ); - op.WriteLine( "

RunUO Server Status

" ); - op.WriteLine( " Online clients:
" ); - op.WriteLine( " " ); - op.WriteLine( " " ); - op.WriteLine( " " ); - op.WriteLine( " " ); + Directory.CreateDirectory("web"); + } - foreach ( NetState state in NetState.Instances ) + using (var op = new StreamWriter("web/status.html")) + { + op.WriteLine(""); + op.WriteLine(""); + op.WriteLine(" "); + op.WriteLine(" " + ServerList.ServerName + " Server Status"); + op.WriteLine(" "); + op.WriteLine(" "); + op.WriteLine(" "); + op.WriteLine("

RunUO Server Status

"); + op.WriteLine("

Online clients

"); + op.WriteLine("
NameLocationKillsKarma / Fame
"); + op.WriteLine(" "); + + var index = 0; + + foreach (var m in NetState.Instances.Where(state => state.Mobile != null).Select(state => state.Mobile)) { - Mobile m = state.Mobile; + ++index; - if ( m != null ) + var g = m.Guild as Guild; + + op.Write(" " ); + op.Write(Encode(g.Abbreviation)); + + op.Write(']'); } + else + { + op.Write(Encode(m.Name)); + } + + op.Write(""); } - op.WriteLine( " " ); - op.WriteLine( "
NameLocationKillsKarma/Fame
"); + + if (g != null) { - Guild g = m.Guild as Guild; + op.Write(Encode(m.Name)); + op.Write(" ["); - op.Write( "
" ); + var title = m.GuildTitle; - if ( g != null ) + title = title != null ? title.Trim() : String.Empty; + + if (title.Length > 0) { - op.Write( Encode( m.Name ) ); - op.Write( " [" ); - - string title = m.GuildTitle; - - if ( title != null ) - title = title.Trim(); - else - title = ""; - - if ( title.Length > 0 ) - { - op.Write( Encode( title ) ); - op.Write( ", " ); - } - - op.Write( Encode( g.Abbreviation ) ); - - op.Write( ']' ); - } - else - { - op.Write( Encode( m.Name ) ); + op.Write(Encode(title)); + op.Write(", "); } - op.Write( "" ); - op.Write( m.X ); - op.Write( ", " ); - op.Write( m.Y ); - op.Write( ", " ); - op.Write( m.Z ); - op.Write( " (" ); - op.Write( m.Map ); - op.Write( ")" ); - op.Write( m.Kills ); - op.Write( "" ); - op.Write( m.Karma ); - op.Write( " / " ); - op.Write( m.Fame ); - op.WriteLine( "
"); + op.Write(m.X); + op.Write(", "); + op.Write(m.Y); + op.Write(", "); + op.Write(m.Z); + op.Write(" ("); + op.Write(m.Map); + op.Write(")"); + op.Write(m.Kills); + op.Write(""); + op.Write(m.Karma); + op.Write(" / "); + op.Write(m.Fame); + op.WriteLine("
" ); - op.WriteLine( " " ); - op.WriteLine( "" ); + op.WriteLine(" "); + op.WriteLine(" "); + op.WriteLine(" "); + op.WriteLine(""); + } + + lock (_StatusLock) + { + _StatusPage = File.ReadAllText("web/status.html"); + _StatusBuffer = Encoding.UTF8.GetBytes(_StatusPage); } } }