Created
August 24, 2011 12:48
-
-
Save jcdickinson/1167986 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.IO; | |
using System.Threading; | |
using System.Net; | |
using System.Collections.Concurrent; | |
namespace ConsoleApplication26 | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
WebConsoleListener.Instance.Start(); | |
Console.WriteLine("Press any key to send data..."); | |
while (true) | |
{ | |
Thread.Sleep(100); | |
Console.WriteLine("test"); | |
} | |
} | |
} | |
class WebConsoleListener | |
{ | |
public static readonly WebConsoleListener Instance = new WebConsoleListener(); | |
private HttpListener _listener; | |
private HashSet<WebConsoleContext> _contexts = new HashSet<WebConsoleContext>(); | |
private WebConsoleListener() | |
{ | |
_listener = new HttpListener(); | |
_listener.Prefixes.Add("http://+:9090/"); | |
} | |
public void Start() | |
{ | |
if(WebConsoleWriter.Instance.Install()) | |
{ | |
_listener.Start(); | |
GetContextAsyncLoop(null); | |
} | |
} | |
private void GetContextAsyncLoop(IAsyncResult result) | |
{ | |
try | |
{ | |
if (result != null) | |
{ | |
var ctx = new WebConsoleContext(_listener.EndGetContext(result)); | |
lock (_contexts) | |
_contexts.Add(ctx); | |
} | |
_listener.BeginGetContext(GetContextAsyncLoop, null); | |
} | |
catch | |
{ | |
// TODO: | |
} | |
} | |
public void NotifyData(string value) | |
{ | |
lock (_contexts) | |
{ | |
foreach (var item in _contexts) | |
{ | |
item.Notify(value); | |
} | |
_contexts.RemoveWhere(x => x.IsCompleted); | |
} | |
} | |
} | |
class WebConsoleContext | |
{ | |
private HttpListenerContext _context; | |
private const int ResetAfter = 15000; | |
private EndPoint _rep; | |
private object _lock = new object(); | |
private Timer _timer; | |
private StreamWriter _sw; | |
public bool IsCompleted | |
{ | |
get | |
{ | |
lock (_lock) | |
{ | |
return _sw == null; | |
} | |
} | |
} | |
public WebConsoleContext(HttpListenerContext context) | |
{ | |
_context = context; | |
_rep = context.Request.RemoteEndPoint; | |
_timer = new Timer(EndRequest, null, ResetAfter, Timeout.Infinite); | |
_context.Response.StatusCode = 200; | |
_context.Response.StatusDescription = "OK"; | |
_context.Response.ContentEncoding = Encoding.UTF8; | |
_context.Response.ContentType = "text/html"; | |
_context.Response.SendChunked = true; | |
_sw = new StreamWriter(_context.Response.OutputStream, Encoding.UTF8); | |
_sw.WriteLine("<html>"); | |
_sw.WriteLine("<body style='background-color:black;font-family:Consolas'>"); | |
} | |
public bool Notify(string value) | |
{ | |
lock (_lock) | |
{ | |
if (_sw != null) | |
{ | |
_sw.Write(value); | |
_sw.WriteLine(); | |
_sw.Flush(); | |
return true; | |
} | |
return false; | |
} | |
} | |
private void EndRequest(object state) | |
{ | |
var sw = Interlocked.Exchange(ref _sw, null); | |
if (sw != null) | |
{ | |
sw.WriteLine("<script type='text/javascript'>location.reload(true);</script>"); | |
sw.Dispose(); | |
_context.Response.Close(); | |
_timer.Dispose(); | |
} | |
} | |
public override int GetHashCode() | |
{ | |
return _rep.GetHashCode(); | |
} | |
public override bool Equals(object obj) | |
{ | |
var c = obj as WebConsoleContext; | |
if (!object.ReferenceEquals(c, null)) | |
{ | |
return c._rep.Equals(_rep); | |
} | |
return false; | |
} | |
} | |
class WebConsoleWriter : TextWriter | |
{ | |
public static readonly WebConsoleWriter Instance = new WebConsoleWriter(); | |
private TextWriter _original; | |
private WebConsoleWriter() | |
{ | |
} | |
public bool Install() | |
{ | |
if (Interlocked.CompareExchange(ref _original, Console.Out, null) == null) | |
{ | |
Console.SetOut(this); | |
return true; | |
} | |
return false; | |
} | |
public override Encoding Encoding | |
{ | |
get { return _original.Encoding; } | |
} | |
public override void Write(char value) | |
{ | |
Write(value.ToString()); | |
} | |
public override void Write(string value) | |
{ | |
_original.Write(value); | |
value = value.Replace(" ", " ").Replace("<", "<").Replace("\r\n", "<br />"); | |
switch (Console.ForegroundColor) | |
{ | |
case ConsoleColor.Black: | |
value = "<span style='color:black'>" + value; | |
break; | |
case ConsoleColor.Blue: | |
value = "<span style='color:blue'>" + value; | |
break; | |
case ConsoleColor.Cyan: | |
value = "<span style='color:cyan'>" + value; | |
break; | |
case ConsoleColor.DarkBlue: | |
value = "<span style='color:darkBlue'>" + value; | |
break; | |
case ConsoleColor.DarkCyan: | |
value = "<span style='color:darkCyan'>" + value; | |
break; | |
case ConsoleColor.DarkGray: | |
value = "<span style='color:#777777'>" + value; | |
break; | |
case ConsoleColor.DarkGreen: | |
value = "<span style='color:darkGreen'>" + value; | |
break; | |
case ConsoleColor.DarkMagenta: | |
value = "<span style='color:darkMagenta'>" + value; | |
break; | |
case ConsoleColor.DarkRed: | |
value = "<span style='color:darkRed'>" + value; | |
break; | |
case ConsoleColor.DarkYellow: | |
value = "<span style='color:darkYellow'>" + value; | |
break; | |
case ConsoleColor.Gray: | |
value = "<span style='color:gray'>" + value; | |
break; | |
case ConsoleColor.Green: | |
value = "<span style='color:green'>" + value; | |
break; | |
case ConsoleColor.Magenta: | |
value = "<span style='color:magenta'>" + value; | |
break; | |
case ConsoleColor.Red: | |
value = "<span style='color:red'>" + value; | |
break; | |
case ConsoleColor.White: | |
value = "<span style='color:white'>" + value; | |
break; | |
case ConsoleColor.Yellow: | |
value = "<span style='color:yellow'>" + value; | |
break; | |
} | |
WebConsoleListener.Instance.NotifyData(value + "</span>"); | |
} | |
public override void WriteLine(string value) | |
{ | |
Write(value + "\r\n"); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment