Use AnyEvent to stand up a TLS server

I have written select based TLS servers before, but I want to do it the right way, by using AnyEvent and an event loop.

So first here is a TLS client that works with another TLS server I wrote using select.

Writer.pl, connects to the server and sends 3 short messages and disconnects

#!/usr/bin/env perl use strict; use warnings; use AnyEvent; use AnyEvent::Log; use AnyEvent::Handle; use AnyEvent::Socket; use EV; use Data::Dumper; $AnyEvent::Log::FILTER->level ("trace"); my $handle; my @queue; tcp_connect "127.0.0.1", 9999, sub { my ($fh) = @_; print "Before push_write\n"; push (@queue, "XX\n"); push (@queue, "YY\n"); push (@queue, "ZZ\n"); print "After push_write\n"; $handle = new AnyEvent::Handle ( fh => $fh, tls => "connect", tls_ctx => { verify => 0 }, on_error => sub { my ($xhandle, $fatal, $message) = @_; print "on_error: ($xhandle) ($fatal) ($message)\n"; exit 1; }, on_eof => sub { my ($handle) = @_; print "on_eof:\n"; exit 0; }, on_drain => sub { my ($handle) = @_; print "on_drain:\n"; if (@queue) { my $write = shift @queue; print "Write :$write"; $handle->push_write ($write); } else { print "Queue is empty\n"; $handle->push_shutdown (); } }, on_starttls => sub { my ($handle, $success, $error) = @_; print "on_starttls ($success) ($error)\n"; return; } ); }; EV::run;

This works with an IO::Select based server.

Now to create the TLS server via AnyEvent

I metacpan'd my fingers till they bled, to find working example code. But Alas I could not get it to work, and I have no idea what I am doing, not doing or just am an idiot with.

Using the Metacpan article for AnyEvent::Handle, in the NONFREQUENTLY-ASKED-QUESTIONS, there is a small snippet that seems that it should work.

tcp_server undef, $port, sub { my ($fh) = @_; my $handle = new AnyEvent::Handle fh => $fh, tls => "accept", tls_ctx => { cert_file => "my-server-keycert.pem" }, ...

So here is my attempt to write it into a server.

Server4.pl

#!/usr/bin/env perl use strict; use warnings; use Data::Dumper; use AnyEvent; use AnyEvent::Handle; use AnyEvent::Socket; use AnyEvent::Log; use IO::Socket::SSL; use EV; use Cpanel::JSON::XS; use Path::Tiny qw(path); $IO::Socket::SSL::DEBUG = 3; $AnyEvent::Log::FILTER->level ("trace"); my $json_obj = Cpanel::JSON::XS->new->ascii->pretty(1)->allow_nonref; my $config_file = Path::Tiny::path ("config.json"); die "Must have config file" if (!$config_file->exists); my $config_raw = $config_file->slurp (); my $config; my $ret = eval { $config = $json_obj->decode ($config_raw); }; if (!$ret) { die "Error Parsing JSON\n$@\n"; } tcp_server $config->{LocalAddr}, $config->{LocalPort}, sub { my ($fh) = @_; print "host started\n"; my $handle = new AnyEvent::Handle ( fh => $fh, tls => "accept", tls_ctx => { cert_file => $config->{cert_file}, key_file => $config->{key_file} }, on_read => sub { my ($handle) = @_; print "ON_READ :" . $handle->{rbuf} . ":\n"; }, on_eof => sub { my ($handle) = @_; print "ON_EOF\n"; }, on_error => sub { my ($handle, $fatal, $message) = @_; print "ON_ERROR ($fatal) ($message)\n"; }, ); print "Handle created :$handle:\n"; }; print "Loop started\n"; EV::run;

So when I run it, I see Loop Started, and netstat -anop says it is listening on 127.0.0.1:9999, per the config file. I see the message "Loop Started".

In another window I start Writer.pl

I get the server messages "host started" and "Handle created"

Writer.pl tries to Write XX the first of 3 short messages, then gets an on_eof. And exits out of the program.

Here is the server side of the window output

julian@work:~/git/LLMAssistant/reference/server$ ./Server4.pl 2023-08-17 19:18:28.000000 -0500 info AnyEvent: Autodetected model 'A +nyEvent::Impl::EV', using it. Loop started host started Handle created :AnyEvent::Handle=HASH(0x555b2b5d6eb0): host started Handle created :AnyEvent::Handle=HASH(0x555b2aa87610): host started Handle created :AnyEvent::Handle=HASH(0x555b2aa876d0): ^C

Here is the output of the client side window

julian@work:~/git/LLMAssistant/reference/client$ ./Writer.pl 2023-08-17 19:18:32.000000 -0500 info AnyEvent: Autodetected model 'A +nyEvent::Impl::EV', using it. Before push_write After push_write on_drain: Write :XX on_eof: julian@work:~/git/LLMAssistant/reference/client$ ./Writer.pl 2023-08-17 19:18:33.000000 -0500 info AnyEvent: Autodetected model 'A +nyEvent::Impl::EV', using it. Before push_write After push_write on_drain: Write :XX on_eof: julian@work:~/git/LLMAssistant/reference/client$ ./Writer.pl 2023-08-17 19:18:35.000000 -0500 info AnyEvent: Autodetected model 'A +nyEvent::Impl::EV', using it. Before push_write After push_write on_drain: Write :XX on_eof:

My config file is:

{ "LocalAddr": "127.0.0.1", "LocalPort": 9999, "cert_file": "cert.pem", "key_file": "key.pem" }

The cert and key are self signed cert files

Any advice?

On how I can get this to work?


In reply to Using AnyEvent to create a TLS server by Bodger

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.