2020-11-22 Writing Servers in Perl using Mojo::IOLoop

I’m thinking of rewriting Phoebe using Mojo::IOLoop instead of Net::Server. One problem I needed to solve was listening on different ports (e.g. 443 and 1965), for different hostnames (alexschroeder.ch, emacswiki.org, communitywiki.org, transjovian.org, toki.transjovian.org, vault.transjovian.org, next.oddmuse.org), with different TLS certificates...

This is what I had:

Mojo::IOLoop->server({port ⇒ ... , address ⇒ ... , tls ⇒ 1, tls_cert ⇒ ..., tls_key ⇒ ... } ⇒ sub { ... })

I started wondering: how can I have multiple ports, multiple addresses, and multiple TLS certs in here? Can they take arrays? The man pages was inconclusive. I looked at the source. The address and port are passed on to IO::Socket::IP. I saw something about PeerAddrInfo... and it got more and more confusing, so I asked on the Perl IRC channel.

“What on earth are you doing, and why do you believe that’s the solution? – LeoNerd

I don’t know why I often end up in these dead ends when I read the man pages for these packages.

If you want to listen on multiple ports, you use multiple servers – LeoNerd

I... I guess that makes sense!

So here’s something that works:

use Mojo::IOLoop;
use Modern::Perl;

# Listen on port 3000
for my $address (qw(localhost 127.0.0.2)) {
  for my $port (qw(79 70)) {
    Mojo::IOLoop->server({address => $address, port => $port} => sub {
      my ($loop, $stream) = @_;
      $stream->on(read => \&echo)})}};

sub echo {
  my ($stream, $bytes) = @_;
  # Write response
  $stream->write("Echo: $bytes");
  $stream->close_gracefully();
}

# Start event loop if necessary
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;

Starting it needs sudo because the ports are below 1024: gopher is on port 70 and finger is on port 79.

sudo perl test.pl

Testing it:

$ echo alex | netcat localhost 70
Echo: alex
$ echo alex | netcat localhost 79
Echo: alex
$ echo alex | netcat 127.0.0.1 79
Ncat: Connection refused.
$ echo alex | netcat 127.0.0.2 79
Echo: alex
$ finger alex@localhost
Echo: alex
$ finger berta@127.0.0.1
finger: connect: Connection refused
$ finger berta@127.0.0.2
Echo: berta

Yes! I think I can work with that. 🙂

Comments


Please make sure you contribute only your own work, or work licensed under the GNU Free Documentation License. Note: in order to facilitate peer review and fight vandalism, we will store your IP number for a number of days. See Privacy Policy for more information. See Info for text formatting rules. You can edit the comment page if you need to fix typos. You can subscribe to new comments by email without leaving a comment.

To save this page you must answer this question:

Just say HELLO

Referrers: BACK TO THE DUNGEON!