File Coverage

blib/lib/AnyEvent/MP/Transport.pm
Criterion Covered Total %
statement 19 21 90.4
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 26 28 92.8


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             AnyEvent::MP::Transport - actual transport protocol handler
4              
5             =head1 SYNOPSIS
6              
7             use AnyEvent::MP::Transport;
8              
9             =head1 DESCRIPTION
10              
11             This module implements (and documents) the actual transport protocol for
12             AEMP.
13              
14             See the "PROTOCOL" section below if you want to write another client for
15             this protocol.
16              
17             =head1 FUNCTIONS/METHODS
18              
19             =over 4
20              
21             =cut
22              
23             package AnyEvent::MP::Transport;
24              
25 1     1   1391 use common::sense;
  1         2  
  1         9  
26              
27 1     1   58 use Scalar::Util ();
  1         2  
  1         18  
28 1     1   6 use List::Util ();
  1         1  
  1         13  
29 1     1   956 use MIME::Base64 ();
  1         766  
  1         18  
30 1     1   954 use Storable ();
  1         3496  
  1         29  
31 1     1   8 use JSON::XS ();
  1         2  
  1         16  
32              
33 1     1   432 use Digest::MD6 ();
  0            
  0            
34             use Digest::HMAC_MD6 ();
35              
36             use AE ();
37             use AnyEvent::Socket ();
38             use AnyEvent::Handle 4.92 ();
39              
40             use AnyEvent::MP::Config ();
41              
42             our $PROTOCOL_VERSION = 1;
43              
44             our @HOOK_CONNECT; # called at connect/accept time
45             our @HOOK_GREETING; # called at greeting1 time
46             our @HOOK_CONNECTED; # called at data phase
47             our @HOOK_DESTROY; # called at destroy time
48             our %HOOK_PROTOCOL = (
49             "aemp-dataconn" => sub {
50             require AnyEvent::MP::DataConn;
51             &AnyEvent::MP::DataConn::_inject;
52             },
53             );
54              
55             =item $listener = mp_listener $host, $port, <constructor-args>
56              
57             Creates a listener on the given host/port using
58             C<AnyEvent::Socket::tcp_server>.
59              
60             See C<new>, below, for constructor arguments.
61              
62             Defaults for peerhost, peerport and fh are provided.
63              
64             =cut
65              
66             sub mp_server($$;%) {
67             my ($host, $port, %arg) = @_;
68              
69             AnyEvent::Socket::tcp_server $host, $port, sub {
70             my ($fh, $host, $port) = @_;
71              
72             my $tp = new AnyEvent::MP::Transport
73             fh => $fh,
74             peerhost => $host,
75             peerport => $port,
76             %arg,
77             ;
78             $tp->{keepalive} = $tp;
79             }, delete $arg{prepare}
80             }
81              
82             =item $guard = mp_connect $host, $port, <constructor-args>, $cb->($transport)
83              
84             =cut
85              
86             sub mp_connect {
87             my $release = pop;
88             my ($host, $port, @args) = @_;
89              
90             new AnyEvent::MP::Transport
91             connect => [$host, $port],
92             peerhost => $host,
93             peerport => $port,
94             release => $release,
95             @args,
96             ;
97             }
98              
99             =item new AnyEvent::MP::Transport
100              
101             # immediately starts negotiation
102             my $transport = new AnyEvent::MP::Transport
103             # mandatory
104             fh => $filehandle,
105             local_id => $identifier,
106             on_recv => sub { receive-callback },
107             on_error => sub { error-callback },
108              
109             # optional
110             on_eof => sub { clean-close-callback },
111             on_connect => sub { successful-connect-callback },
112             greeting => { key => value },
113              
114             # tls support
115             tls_ctx => AnyEvent::TLS,
116             peername => $peername, # for verification
117             ;
118              
119             =cut
120              
121             sub new {
122             my ($class, %arg) = @_;
123              
124             my $self = bless \%arg, $class;
125              
126             {
127             Scalar::Util::weaken (my $self = $self);
128              
129             my $config = $AnyEvent::MP::Kernel::CONFIG;
130              
131             my $timeout = $config->{monitor_timeout};
132             my $lframing = $config->{framing_format};
133             my $auth_snd = $config->{auth_offer};
134             my $auth_rcv = $config->{auth_accept};
135              
136             $self->{secret} = $config->{secret}
137             unless exists $self->{secret};
138              
139             my $secret = $self->{secret};
140              
141             if (exists $config->{cert}) {
142             $self->{tls_ctx} = {
143             sslv2 => 0,
144             sslv3 => 0,
145             tlsv1 => 1,
146             verify => 1,
147             cert => $config->{cert},
148             ca_cert => $config->{cert},
149             verify_require_client_cert => 1,
150             };
151             }
152              
153             $self->{hdl} = new AnyEvent::Handle
154             +($self->{fh} ? (fh => $self->{fh}) : (connect => $self->{connect})),
155             autocork => $config->{autocork},
156             no_delay => exists $config->{nodelay} ? $config->{nodelay} : 1,
157             keepalive => 1,
158             on_error => sub {
159             $self->error ($_[2]);
160             },
161             rtimeout => $timeout,
162             ;
163              
164             my $greeting_kv = $self->{local_greeting} ||= {};
165              
166             $greeting_kv->{tls} = "1.0" if $self->{tls_ctx};
167             $greeting_kv->{provider} = "AE-$AnyEvent::MP::VERSION"; # MP.pm might not be loaded, so best effort :(
168             $greeting_kv->{peeraddr} = AnyEvent::Socket::format_hostport $self->{peerhost}, $self->{peerport};
169              
170             my $protocol = $self->{protocol} || "aemp";
171              
172             # can modify greeting_kv
173             $_->($self) for $protocol eq "aemp" ? @HOOK_CONNECT : ();
174              
175             # send greeting
176             my $lgreeting1 = "$protocol;$PROTOCOL_VERSION"
177             . ";$AnyEvent::MP::Kernel::NODE"
178             . ";" . (join ",", @$auth_rcv)
179             . ";" . (join ",", @$lframing)
180             . (join "", map ";$_=$greeting_kv->{$_}", keys %$greeting_kv);
181              
182             my $lgreeting2 = MIME::Base64::encode_base64 AnyEvent::MP::Kernel::nonce (66), "";
183              
184             $self->{hdl}->push_write ("$lgreeting1\012$lgreeting2\012");
185             return unless $self;
186              
187             # expect greeting
188             $self->{hdl}->rbuf_max (4 * 1024);
189             $self->{hdl}->push_read (line => sub {
190             my $rgreeting1 = $_[1];
191              
192             my ($aemp, $version, $rnode, $auths, $framings, @kv) = split /;/, $rgreeting1;
193              
194             $self->{remote_node} = $rnode;
195              
196             $self->{remote_greeting} = {
197             map /^([^=]+)(?:=(.*))?/ ? ($1 => $2) : (),
198             @kv
199             };
200              
201             # maybe upgrade the protocol
202             if ($protocol eq "aemp" and $aemp =~ /^aemp-\w+$/) {
203             # maybe check for existence of the protocol handler?
204             $self->{protocol} = $protocol = $aemp;
205             }
206              
207             $_->($self) for $protocol eq "aemp" ? @HOOK_GREETING : ();
208              
209             if ($aemp ne $protocol and $aemp ne "aemp") {
210             return $self->error ("unparsable greeting, expected '$protocol', got '$aemp'");
211             } elsif ($version != $PROTOCOL_VERSION) {
212             return $self->error ("version mismatch (we: $PROTOCOL_VERSION, they: $version)");
213             } elsif ($protocol eq "aemp") {
214             if ($rnode eq $AnyEvent::MP::Kernel::NODE) {
215             return $self->error ("I refuse to talk to myself");
216             } elsif ($AnyEvent::MP::Kernel::NODE{$rnode} && $AnyEvent::MP::Kernel::NODE{$rnode}{transport}) {
217             return $self->error ("$rnode already connected, not connecting again.");
218             }
219             }
220              
221             # read nonce
222             $self->{hdl}->push_read (line => sub {
223             my $rgreeting2 = $_[1];
224              
225             "$lgreeting1\012$lgreeting2" ne "$rgreeting1\012$rgreeting2" # echo attack?
226             or return $self->error ("authentication error, echo attack?");
227              
228             my $tls = $self->{tls_ctx} && 1 == int $self->{remote_greeting}{tls};
229              
230             my $s_auth;
231             for my $auth_ (split /,/, $auths) {
232             if (grep $auth_ eq $_, @$auth_snd and ($auth_ !~ /^tls_/ or $tls)) {
233             $s_auth = $auth_;
234             last;
235             }
236             }
237              
238             defined $s_auth
239             or return $self->error ("$auths: no common auth type supported");
240              
241             my $s_framing;
242             for my $framing_ (split /,/, $framings) {
243             if (grep $framing_ eq $_, @$lframing) {
244             $s_framing = $framing_;
245             last;
246             }
247             }
248              
249             defined $s_framing
250             or return $self->error ("$framings: no common framing method supported");
251              
252             my $key;
253             my $lauth;
254              
255             if ($tls) {
256             $self->{tls} = $lgreeting2 lt $rgreeting2 ? "connect" : "accept";
257             $self->{hdl}->starttls ($self->{tls}, $self->{tls_ctx});
258             return unless $self->{hdl}; # starttls might destruct us
259              
260             $lauth =
261             $s_auth eq "tls_anon" ? ""
262             : $s_auth eq "tls_md6_64_256" ? Digest::MD6::md6_hex "$lgreeting1\012$lgreeting2\012$rgreeting1\012$rgreeting2\012"
263             : return $self->error ("$s_auth: fatal, selected unsupported snd auth method");
264              
265             } elsif (length $secret) {
266             return $self->error ("$s_auth: fatal, selected unsupported snd auth method")
267             unless $s_auth eq "hmac_md6_64_256"; # hardcoded atm.
268              
269             $key = Digest::MD6::md6 $secret;
270             # we currently only support hmac_md6_64_256
271             $lauth = Digest::HMAC_MD6::hmac_md6_hex $key, "$lgreeting1\012$lgreeting2\012$rgreeting1\012$rgreeting2\012", 64, 256;
272              
273             } else {
274             return $self->error ("unable to handshake TLS and no shared secret configured");
275             }
276              
277             $self->{hdl}->push_write ("$s_auth;$lauth;$s_framing\012");
278             return unless $self;
279              
280             # read the authentication response
281             $self->{hdl}->push_read (line => sub {
282             my ($hdl, $rline) = @_;
283              
284             my ($auth_method, $rauth2, $r_framing) = split /;/, $rline;
285              
286             my $rauth =
287             $auth_method eq "hmac_md6_64_256" ? Digest::HMAC_MD6::hmac_md6_hex $key, "$rgreeting1\012$rgreeting2\012$lgreeting1\012$lgreeting2\012", 64, 256
288             : $auth_method eq "cleartext" ? unpack "H*", $secret
289             : $auth_method eq "tls_anon" ? ($tls ? "" : "\012\012") # \012\012 never matches
290             : $auth_method eq "tls_md6_64_256" ? ($tls ? Digest::MD6::md6_hex "$rgreeting1\012$rgreeting2\012$lgreeting1\012$lgreeting2\012" : "\012\012")
291             : return $self->error ("$auth_method: fatal, selected unsupported rcv auth method");
292              
293             if ($rauth2 ne $rauth) {
294             return $self->error ("authentication failure/shared secret mismatch");
295             }
296              
297             $self->{s_framing} = $s_framing;
298              
299             $hdl->rbuf_max (undef);
300              
301             # we rely on TCP retransmit timeouts and keepalives
302             $self->{hdl}->rtimeout (undef);
303              
304             $self->{remote_greeting}{untrusted} = 1
305             if $auth_method eq "tls_anon";
306              
307             if ($protocol eq "aemp" and $self->{hdl}) {
308             # listener-less node need to continuously probe
309             unless (@$AnyEvent::MP::Kernel::LISTENER) {
310             $self->{hdl}->wtimeout ($timeout);
311             $self->{hdl}->on_wtimeout (sub { $self->{send}->([]) });
312             }
313              
314             # receive handling
315              
316             my $push_write = $hdl->can ("push_write");
317             my $push_read = $hdl->can ("push_read");
318              
319             if ($s_framing eq "json") {
320             $self->{send} = sub {
321             $push_write->($hdl, JSON::XS::encode_json $_[0]);
322             };
323             } else {
324             $self->{send} = sub {
325             $push_write->($hdl, $s_framing => $_[0]);
326             };
327             }
328              
329             if ($r_framing eq "json") {
330             my $coder = JSON::XS->new->utf8;
331              
332             $hdl->on_read (sub {
333             local $AnyEvent::MP::Kernel::SRCNODE = $self->{node};
334              
335             AnyEvent::MP::Kernel::_inject (@$_)
336             for $coder->incr_parse (delete $_[0]{rbuf});
337              
338             ()
339             });
340             } else {
341             my $rmsg; $rmsg = $self->{rmsg} = sub {
342             $push_read->($_[0], $r_framing => $rmsg);
343              
344             local $AnyEvent::MP::Kernel::SRCNODE = $self->{node};
345             AnyEvent::MP::Kernel::_inject (@{ $_[1] });
346             };
347             eval {
348             $push_read->($_[0], $r_framing => $rmsg);
349             };
350             Scalar::Util::weaken $rmsg;
351             return $self->error ("$r_framing: unusable remote framing")
352             if $@;
353             }
354             }
355              
356             $self->connected;
357             });
358             });
359             });
360             }
361              
362             $self
363             }
364              
365             sub error {
366             my ($self, $msg) = @_;
367              
368             delete $self->{keepalive};
369              
370             if ($self->{protocol}) {
371             $HOOK_PROTOCOL{$self->{protocol}}->($self, $msg);
372             } else {
373             $AnyEvent::MP::Kernel::WARN->(9, "$self->{peerhost}:$self->{peerport} $msg");#d#
374              
375             $self->{node}->transport_error (transport_error => $self->{node}{id}, $msg)
376             if $self->{node} && $self->{node}{transport} == $self;
377             }
378              
379             (delete $self->{release})->()
380             if exists $self->{release};
381            
382             # $AnyEvent::MP::Kernel::WARN->(7, "$self->{peerhost}:$self->{peerport}: $msg");
383             $self->destroy;
384             }
385              
386             sub connected {
387             my ($self) = @_;
388              
389             delete $self->{keepalive};
390              
391             if ($self->{protocol}) {
392             $self->{hdl}->on_error (undef);
393             $HOOK_PROTOCOL{$self->{protocol}}->($self, undef);
394             } else {
395             $AnyEvent::MP::Kernel::WARN->(9, "$self->{peerhost}:$self->{peerport} connected as $self->{remote_node}");
396              
397             my $node = AnyEvent::MP::Kernel::add_node ($self->{remote_node});
398             Scalar::Util::weaken ($self->{node} = $node);
399             $node->transport_connect ($self);
400              
401             $_->($self) for @HOOK_CONNECTED;
402             }
403              
404             (delete $self->{release})->()
405             if exists $self->{release};
406             }
407              
408             sub destroy {
409             my ($self) = @_;
410              
411             (delete $self->{release})->()
412             if exists $self->{release};
413              
414             $self->{hdl}->destroy
415             if $self->{hdl};
416              
417             $_->($self) for $self->{protocol} ? () : @HOOK_DESTROY;
418             }
419              
420             sub DESTROY {
421             my ($self) = @_;
422              
423             $self->destroy;
424             }
425              
426             =back
427              
428             =head1 PROTOCOL
429              
430             The AEMP protocol is comparatively simple, and consists of three phases
431             which are symmetrical for both sides: greeting (followed by optionally
432             switching to TLS mode), authentication and packet exchange.
433              
434             The protocol is designed to allow both full-text and binary streams.
435              
436             The greeting consists of two text lines that are ended by either an ASCII
437             CR LF pair, or a single ASCII LF (recommended).
438              
439             =head2 GREETING
440              
441             All the lines until after authentication must not exceed 4kb in length,
442             including line delimiter. Afterwards there is no limit on the packet size
443             that can be received.
444              
445             =head3 First Greeting Line
446              
447             Example:
448              
449             aemp;0;rain;tls_md6_64_256,hmac_md6_64_256,tls_anon,cleartext;json,storable;timeout=12;peeraddr=10.0.0.1:48082
450              
451             The first line contains strings separated (not ended) by C<;>
452             characters. The first five strings are fixed by the protocol, the
453             remaining strings are C<KEY=VALUE> pairs. None of them may contain C<;>
454             characters themselves (when escaping is needed, use C<%3b> to represent
455             C<;> and C<%25> to represent C<%>)-
456              
457             The fixed strings are:
458              
459             =over 4
460              
461             =item protocol identification
462              
463             The constant C<aemp> to identify this protocol.
464              
465             =item protocol version
466              
467             The protocol version supported by this end, currently C<1>. If the
468             versions don't match then no communication is possible. Minor extensions
469             are supposed to be handled through additional key-value pairs.
470              
471             =item the node ID
472              
473             This is the node ID of the connecting node.
474              
475             =item the acceptable authentication methods
476              
477             A comma-separated list of authentication methods supported by the
478             node. Note that AnyEvent::MP supports a C<hex_secret> authentication
479             method that accepts a clear-text password (hex-encoded), but will not use
480             this authentication method itself.
481              
482             The receiving side should choose the first authentication method it
483             supports.
484              
485             =item the acceptable framing formats
486              
487             A comma-separated list of packet encoding/framing formats understood. The
488             receiving side should choose the first framing format it supports for
489             sending packets (which might be different from the format it has to accept).
490              
491             =back
492              
493             The remaining arguments are C<KEY=VALUE> pairs. The following key-value
494             pairs are known at this time:
495              
496             =over 4
497              
498             =item provider=<module-version>
499              
500             The software provider for this implementation. For AnyEvent::MP, this is
501             C<AE-0.0> or whatever version it currently is at.
502              
503             =item peeraddr=<host>:<port>
504              
505             The peer address (socket address of the other side) as seen locally.
506              
507             =item tls=<major>.<minor>
508              
509             Indicates that the other side supports TLS (version should be 1.0) and
510             wishes to do a TLS handshake.
511              
512             =back
513              
514             =head3 Second Greeting Line
515              
516             After this greeting line there will be a second line containing a
517             cryptographic nonce, i.e. random data of high quality. To keep the
518             protocol text-only, these are usually 32 base64-encoded octets, but
519             it could be anything that doesn't contain any ASCII CR or ASCII LF
520             characters.
521              
522             I<< The two nonces B<must> be different, and an aemp implementation
523             B<must> check and fail when they are identical >>.
524              
525             Example of a nonce line (yes, it's random-looking because it is random
526             data):
527              
528             2XYhdG7/O6epFa4wuP0ujAEx1rXYWRcOypjUYK7eF6yWAQr7gwIN9m/2+mVvBrTPXz5GJDgfGm9d8QRABAbmAP/s
529              
530             =head2 TLS handshake
531              
532             I<< If, after the handshake, both sides indicate interest in TLS, then the
533             connection B<must> use TLS, or fail to continue. >>
534              
535             Both sides compare their nonces, and the side who sent the lower nonce
536             value ("string" comparison on the raw octet values) becomes the client,
537             and the one with the higher nonce the server.
538              
539             =head2 AUTHENTICATION PHASE
540              
541             After the greeting is received (and the optional TLS handshake),
542             the authentication phase begins, which consists of sending a single
543             C<;>-separated line with three fixed strings and any number of
544             C<KEY=VALUE> pairs.
545              
546             The three fixed strings are:
547              
548             =over 4
549              
550             =item the authentication method chosen
551              
552             This must be one of the methods offered by the other side in the greeting.
553              
554             Note that all methods starting with C<tls_> are only valid I<iff> TLS was
555             successfully handshaked (and to be secure the implementation must enforce
556             this).
557              
558             The currently supported authentication methods are:
559              
560             =over 4
561              
562             =item cleartext
563              
564             This is simply the shared secret, lowercase-hex-encoded. This method is of
565             course very insecure if TLS is not used (and not completely secure even
566             if TLS is used), which is why this module will accept, but not generate,
567             cleartext auth replies.
568              
569             =item hmac_md6_64_256
570              
571             This method uses an MD6 HMAC with 64 bit blocksize and 256 bit hash, and
572             requires a shared secret. It is the preferred auth method when a shared
573             secret is available.
574              
575             First, the shared secret is hashed with MD6:
576              
577             key = MD6 (secret)
578              
579             This secret is then used to generate the "local auth reply", by taking
580             the two local greeting lines and the two remote greeting lines (without
581             line endings), appending \012 to all of them, concatenating them and
582             calculating the MD6 HMAC with the key:
583              
584             lauth = HMAC_MD6 key, "lgreeting1\012lgreeting2\012rgreeting1\012rgreeting2\012"
585              
586             This authentication token is then lowercase-hex-encoded and sent to the
587             other side.
588              
589             Then the remote auth reply is generated using the same method, but local
590             and remote greeting lines swapped:
591              
592             rauth = HMAC_MD6 key, "rgreeting1\012rgreeting2\012lgreeting1\012lgreeting2\012"
593              
594             This is the token that is expected from the other side.
595              
596             =item tls_anon
597              
598             This type is only valid I<iff> TLS was enabled and the TLS handshake
599             was successful. It has no authentication data, as the server/client
600             certificate was successfully verified.
601              
602             This authentication type is somewhat insecure, as it allows a
603             man-in-the-middle attacker to change some of the connection parameters
604             (such as the framing format), although there is no known attack that
605             exploits this in a way that is worse than just denying the service.
606              
607             By default, this implementation accepts but never generates this auth
608             reply.
609              
610             =item tls_md6_64_256
611              
612             This type is only valid I<iff> TLS was enabled and the TLS handshake was
613             successful.
614              
615             This authentication type simply calculates:
616              
617             lauth = MD6 "rgreeting1\012rgreeting2\012lgreeting1\012lgreeting2\012"
618              
619             and lowercase-hex encodes the result and sends it as authentication
620             data. No shared secret is required (authentication is done by TLS). The
621             checksum exists only to make tinkering with the greeting hard.
622              
623             =back
624              
625             =item the authentication data
626              
627             The authentication data itself, usually base64 or hex-encoded data, see
628             above.
629              
630             =item the framing protocol chosen
631              
632             This must be one of the framing protocols offered by the other side in the
633             greeting. Each side must accept the choice of the other side, and generate
634             packets in the format it chose itself.
635              
636             =back
637              
638             Example of an authentication reply:
639              
640             hmac_md6_64_256;363d5175df38bd9eaddd3f6ca18aa1c0c4aa22f0da245ac638d048398c26b8d3;json
641              
642             =head2 DATA PHASE
643              
644             After this, packets get exchanged using the chosen framing protocol. It is
645             quite possible that both sides use a different framing protocol.
646              
647             =head2 FULL EXAMPLE
648              
649             This is an actual protocol dump of a handshake, followed by a single data
650             packet. The greater than/less than lines indicate the direction of the
651             transfer only.
652              
653             > aemp;0;anon/57Cs1CggVJjzYaQp13XXg4;tls_md6_64_256,hmac_md6_64_256,tls_anon,cleartext;json,storable;provider=AE-0.8;timeout=12;peeraddr=10.0.0.17:4040
654             > yLgdG1ov/02shVkVQer3wzeuywZK+oraTdEQBmIqWHaegxSGDG4g+HqogLQbvdypFOsoDWJ1Sh4ImV4DMhvUBwTK
655              
656             < aemp;0;ruth;tls_md6_64_256,hmac_md6_64_256,tls_anon,cleartext;json,storable;provider=AE-0.8;timeout=12;peeraddr=10.0.0.1:37108
657             < +xMQXP8ElfNmuvEhsmcp+s2wCJOuQAsPxSg3d2Ewhs6gBnJz+ypVdWJ/wAVrXqlIJfLeVS/CBy4gEGkyWHSuVb1L
658              
659             > hmac_md6_64_256;5ad913855742ae5a03a5aeb7eafa4c78629de136bed6acd73eea36c9e98df44a;json
660              
661             < hmac_md6_64_256;84cd590976f794914c2ca26dac3a207a57a6798b9171289c114de07cf0c20401;json
662             < ["","AnyEvent::MP::_spawn","57Cs1CggVJjzYaQp13XXg4.c","AnyEvent::MP::Global::connect",0,"anon/57Cs1CggVJjzYaQp13XXg4"]
663             ...
664              
665             The shared secret in use was C<8ugxrtw6H5tKnfPWfaSr4HGhE8MoJXmzTT1BWq7sLutNcD0IbXprQlZjIbl7MBKoeklG3IEfY9GlJthC0pENzk>.
666              
667             =head2 SIMPLE HANDSHAKE FOR NON-PERL NODES
668              
669             Implementing the full set of options for handshaking can be a daunting
670             task.
671              
672             If security is not so important (because you only connect locally and
673             control the host, a common case), and you want to interface with an AEMP
674             node from another programming language, then you can also implement a
675             simplified handshake.
676              
677             For example, in a simple implementation you could decide to simply not
678             check the authenticity of the other side and use cleartext authentication
679             yourself. The the handshake is as simple as sending three lines of text,
680             reading three lines of text, and then you can exchange JSON-formatted
681             messages:
682              
683             aemp;1;<nodename>;hmac_md6_64_256;json
684             <nonce>
685             cleartext;<hexencoded secret>;json
686              
687             The nodename should be unique within the network, preferably unique with
688             every connection, the <nonce> could be empty or some random data, and the
689             hexencoded secret would be the shared secret, in lowercase hex (e.g. if
690             the secret is "geheim", the hex-encoded version would be "67656865696d").
691              
692             Note that apart from the low-level handshake and framing protocol, there
693             is a high-level protocol, e.g. for monitoring, building the mesh or
694             spawning. All these messages are sent to the node port (the empty string)
695             and can safely be ignored if you do not need the relevant functionality.
696              
697             =head3 USEFUL HINTS
698              
699             Since taking part in the global protocol to find port groups is
700             nontrivial, hardcoding port names should be considered as well, i.e. the
701             non-Perl node could simply listen to messages for a few well-known ports.
702              
703             Alternatively, the non-Perl node could call a (already loaded) function
704             in the Perl node by sending it a special message:
705              
706             ["", "Some::Function::name", "myownport", 1, 2, 3]
707              
708             This would call the function C<Some::Function::name> with the string
709             C<myownport> and some additional arguments.
710              
711             =head2 MONITORING
712              
713             Monitoring the connection itself is transport-specific. For TCP, all
714             connection monitoring is currently left to TCP retransmit time-outs
715             on a busy link, and TCP keepalive (which should be enabled) for idle
716             connections.
717              
718             This is not sufficient for listener-less nodes, however: they need
719             to regularly send data (30 seconds, or the monitoring interval, is
720             recommended), so TCP actively probes.
721              
722             Future implementations of AnyEvent::Transport might query the kernel TCP
723             buffer after a write timeout occurs, and if it is non-empty, shut down the
724             connections, but this is an area of future research :)
725              
726             =head2 NODE PROTOCOL
727              
728             The transport simply transfers messages, but to implement a full node, a
729             special node port must exist that understands a number of requests.
730              
731             If you are interested in implementing this, drop us a note so we finish
732             the documentation.
733              
734             =head1 SEE ALSO
735              
736             L<AnyEvent::MP>.
737              
738             =head1 AUTHOR
739              
740             Marc Lehmann <schmorp@schmorp.de>
741             http://home.schmorp.de/
742              
743             =cut
744              
745             1
746