summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2012-02-17 13:42:33 +0100
committerYorhel <git@yorhel.nl>2012-02-17 13:42:33 +0100
commit62307659346c05b2da3dcbd4b122d11d571929b2 (patch)
treea5de7850a0d785953fe2695783d0939a0752e370
parent60cd8830d1486264206de93e87271bf45aa37a31 (diff)
perl: Started on Tanja::Link + implemented handshaking
-rw-r--r--doc/proto.pod2
-rw-r--r--perl/Tanja.pm61
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
-