diff options
author | Yorhel <git@yorhel.nl> | 2012-02-17 13:42:33 +0100 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2012-02-17 13:42:33 +0100 |
commit | 62307659346c05b2da3dcbd4b122d11d571929b2 (patch) | |
tree | a5de7850a0d785953fe2695783d0939a0752e370 | |
parent | 60cd8830d1486264206de93e87271bf45aa37a31 (diff) |
perl: Started on Tanja::Link + implemented handshaking
-rw-r--r-- | doc/proto.pod | 2 | ||||
-rw-r--r-- | perl/Tanja.pm | 61 |
2 files changed, 61 insertions, 2 deletions
diff --git a/doc/proto.pod b/doc/proto.pod index 09c3205..5edbc6f 100644 --- a/doc/proto.pod +++ b/doc/proto.pod @@ -11,7 +11,7 @@ sockets and TCP). =head1 HANDSHAKE server: ver,1,0 ser,json,gob - client: ver,1,0 ser,json + client: ver,1.0 ser,json After a client has connected, the server sends the first message. This message is a space-separated list of parameters, followed by a newline character (\n). diff --git a/perl/Tanja.pm b/perl/Tanja.pm index 0f59159..680ef83 100644 --- a/perl/Tanja.pm +++ b/perl/Tanja.pm @@ -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 - |