Sunday, March 13, 2011

Termcast on the Web

The History of Termcast
In the NetHack community, people like to broadcast their games over telnet so others can watch, learn, and/or be impressed. Some wanted to broadcast more than just NetHack games.

Thus, termcast was born.

Anything one could do on a shell, one could do on termcast.  This allowed for activities like showing off tricks in a favorite editor, the thought process of the broadcaster when writing in a programming language, knowledge of various shell commands, CompSci homework, installation processes, the list goes on.

Branching from Telnet
One day while goofing off on CPAN, I discovered HTML::FromANSI, which does just what it sounds like: turn ANSI into HTML. This immediately inspired me to write a proof-of-concept of a web-based termcast. I have never dealt with VT emulators before, so I had no idea if this would even work. So I hacked on something that had a single listening socket, to which I used doy++'s App::Termcast to connect. It served a single page that used a javascript setInterval() timer to update every 0.2s or so. And when I ran it, it worked! It rendered very slowly and killed my CPU, but who cares: I could see the terminal display update live as I did things on the connected terminal!  Though, it seemed pretty daunting to make this in any way efficient, so I gave up on continuing any work on it.

Until now.

Termcast on the web with true streaming
I am now working on App::Termcast::Server and its web component, App::Termcast::Server::Web. It uses clkao++'s Web::Hippie, which utilizes a nice selection of modern streaming tools for the web to process communication from server to client, such as WebSockets, MXHR and (long) polling. It will transparently choose one depending on what the connecting browser supports. For instance, at the time of this writing, Chrome and Safari supports WebSockets, but Firefox doesn't, so the javascript would choose MXHR polling to do the heavy lifting in Firefox.

I am still trying different things out with the application. My first implementation involved a table with 80 <td>s inside 24 <tr>s, with javascript updating individual rows. The process of changing the foreground color and value of the cell (not to mention up to 1920 at the same time, it was a huge bottleneck, so I decided to learn HTML5 and use that if the browser supported it. Now it uses <canvas> and updates cells with the whole different logic from the table implementation, and is noticeably faster to render on-the-fly as well.

I think I am quickly catching up to the functionality of the original termcast application. Though, in my opinion, one of my killer features is the ability to resize your terminal and see the terminal on the web application change sizes as well, so you don't have to assume 80x24 or anything.

I am happy with the progress I am making with the web component of App::Termcast::Server, but I hope others will start writing other components for it. I started on a telnet component, but it doesn't really work. Also, I wrote a small IRC bot (currently somewhat brittle) that announces termcast connections, which is pretty neat.

As always, I am happy to get feedback, and feel free to contribute in any way you can.

Patches welcome!

1 comment: