Bodger has asked for the wisdom of the Perl Monks concerning the following question:
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
On how I can get this to work?
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: Using AnyEvent to create a TLS server
by haukex (Archbishop) on Aug 18, 2023 at 11:40 UTC | |
by Bodger (Acolyte) on Aug 18, 2023 at 13:27 UTC | |
Re: Using AnyEvent to create a TLS server
by cavac (Prior) on Aug 18, 2023 at 07:47 UTC |