Some years ago I learned of existence of (supposedly cool) POE framework for Perl. I tried to use it for some projects, but the learning curve proved to be fatal for my interest.
All the time I felt that POE is great, it's just that I'm too stupid to be able to actively use it.
All information is provided as text – location descriptions, actions, everything.
The thing is that MUD works as TCP server, accessible usually with telnet program, or some specialized programs which add capabilities like scripting. But the core game is played over open TCP connection between client and server. If the connection is lost, you can't play.
Now, this is in direct contrary to HTTP, which is stateless protocol – send request, get response, close connection. Of course there are things like Keep-Alive connections, or push channels, but they all seem to be “not cool".
So, we envisioned a proxy, that would act as http server, but pass information to and from MUD server, keeping connection between MUD and proxy open all the time.
Typical flow of data in it would be:
- proxy gets initial request from client (http)
- proxy opens connection to server, and returns session id to client
- whenever server “says" something, proxy buffers the data for client
- whenever client sends request – proxy returns all data from buffer to him
- if client provides “command" to be sent to mud, it is passed to mud using mud connection associated with given http-session-id.
- if server will close connection – proxy should keep this information for client, together with last (not yet received) messages from server, to be passed to client
If you ever heard about POE or anything like it (for example Twisted in Pythonland), you should see that description of the proxy matches perfectly what POE can (or at least should) do.
Given this, and my previous attempts at using POE, I decided to write it in POE – killing 2 birds with 1 stone – writing program for friend, and learning something new.
Right now, it's not fully completed – i.e. there is no configuration file, logs, and so on, but the program itself works, and works quite nicely (at least – as far as my tests go).
In mud-proxy.pl (which is the proxy itself, test-server.pl is just some test tcp server I wrote to be able to test proxy), important parts are:
my $server = POE::Component::Server::HTTPServer->new( 'port' => 8181, 'handlers' => [ '/mud' => \&handle_requests, '/' => new_handler( 'NotFoundHandler' ), ], );
Which starts the HTTP part of the proxy on tcp port 8181, and adds handler for /mud url.
my $mud = POE::Component::Client::TCP->new( 'RemoteAddress' => '127.0.0.1', 'RemotePort' => '9000', 'Alias' => $client_id, ...
Which starts connection to MUD server, assuming it works on 127.0.0.1:9000.
Once running, you can request http://127.0.0.1:8181/mud to get data from server, and pass your input as cmd http parameters.
For example, sending request:
will send “ls -l" command to mud server.
As far as commands go – proxy adds “\r\n" at the end of cmd, but only if it is not already there.
Of course this proxy can be used with any server, not only MUD. As long as the server uses TCP communication over defined port – it can be proxied to using mud-proxy.
As you will probably notice there are not much of security checks in the code – this is simply because the program (as it is now) is meant to be used as a backend, and be called from some front layer (php? mod_perl? django? whatever), and not directly web browser, though it is of course possible to add security measures, extensive logging, and basically anything that you could find useful.
Finally, I would like to express my sincere “THANK YOU" to all helpful souls on #poe channel on irc.perl.org that helped me whenever I felt lost (approximately every 15 seconds). Without you I wouldn't be able to write it.