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
commitd58dccc8615a5ed4017c9d7612fbdb365aa4c0ea (patch)
treeaf19433a052e223ab7cf5f39842bedfe95a7f132
parentdfa74a754817dcf2da1f9788a9ad4924bb21efb5 (diff)
Started on Tanja::Link + implemented handshaking
-rw-r--r--Tanja.pm61
1 files changed, 60 insertions, 1 deletions
diff --git a/Tanja.pm b/Tanja.pm
index 0f59159..680ef83 100644
--- a/Tanja.pm
+++ b/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
-