Skip to content

Instantly share code, notes, and snippets.

@jcdickinson
Created August 24, 2011 12:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jcdickinson/1167986 to your computer and use it in GitHub Desktop.
Save jcdickinson/1167986 to your computer and use it in GitHub Desktop.
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(" ", "&nbsp;").Replace("<", "&lt;").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