diff options
-rw-r--r-- | Tanja.pm | 61 |
1 files changed, 60 insertions, 1 deletions
@@ -46,6 +46,7 @@ sub session { # Link with another server via an AnyEvent::Handle stream sub link { + return Tanja::Link->new(@_); } @@ -173,7 +174,65 @@ sub DESTROY { } +package Tanja::Link; + +use strict; +use warnings; +use AnyEvent::Handle; +use Errno 'EPIPE'; + + +# Args: Tanja::Server, $server||!$client, AnyEvent::Handle, $error->($message) +# Automatically initiates handshake and stuff. Error callback will also be +# called when the remote side simply disconnected, $message is in that case +# undef. +sub new { + my($own, $serv, $init, $handle, $err) = @_; + my $s = bless { + serv => $serv, + hdl => $handle, + init => $init, + err => $err, + }, $own; + $handle->on_error(sub { $s->_err($! == EPIPE ? undef : $_[2]) }); + # TODO: Better to have a timeout on writes. (Although this buffer limit isn't bad either) + $handle->wbuf_max(5*1024*1024); # This would be really bad. + $s->_handshake; + return $s; +} + + +sub _err { + my($s, $m) = @_; + $s->{hdl}->destroy; + $s->{err} && $s->{err}->($m); +} + + +sub _handshake { + my $s = shift; + + # If we should initiate the handshake, do so + $s->{init} && $s->{hdl}->push_write("ver,1.0 ser,json\012"); + + # Receive handshake from other party + $s->{hdl}->push_read(line => "\012" => sub { + my $ver = ($_[1] =~ /\bver,([^ ]+)\b/) && $1; + my $ser = ($_[1] =~ /\bser,([^ ]+)\b/) && $1; + + # Validate + $s->_err("Invalid handshake: $_[1]") if !$ver || !$ser + || ($s->{init} ? $ver ne '1.0' : !grep /^1\./, split /,/, $ver) + || ($s->{init} ? $ser ne 'json' : !grep $_ eq 'json', split /,/, $ser); + + # Reply with our handshake if we hadn't sent it yet. + !$s->{init} && $s->{hdl}->push_write("ver,1.0 ser,json\012"); + + # TODO: handshake is complete at this point, start regular message exchange. + }); +} + + 1; # vim:noet:sw=4:ts=4 - |