ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-MP/MP/Transport.pm
Revision: 1.48
Committed: Thu Sep 3 20:16:36 2009 UTC (14 years, 9 months ago) by root
Branch: MAIN
Changes since 1.47: +10 -9 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 =head1 NAME
2    
3 root 1.13 AnyEvent::MP::Transport - actual transport protocol handler
4 root 1.1
5     =head1 SYNOPSIS
6    
7     use AnyEvent::MP::Transport;
8    
9     =head1 DESCRIPTION
10    
11 root 1.43 This module implements (and documents) the actual transport protocol for
12     AEMP.
13 root 1.1
14 root 1.7 See the "PROTOCOL" section below if you want to write another client for
15     this protocol.
16 root 1.1
17     =head1 FUNCTIONS/METHODS
18    
19     =over 4
20    
21     =cut
22    
23     package AnyEvent::MP::Transport;
24    
25     use common::sense;
26    
27 root 1.27 use Scalar::Util ();
28     use List::Util ();
29 root 1.1 use MIME::Base64 ();
30     use Storable ();
31 root 1.2 use JSON::XS ();
32 root 1.1
33 root 1.19 use Digest::MD6 ();
34     use Digest::HMAC_MD6 ();
35    
36 root 1.1 use AE ();
37     use AnyEvent::Socket ();
38 root 1.27 use AnyEvent::Handle 4.92 ();
39 root 1.2
40 root 1.30 use AnyEvent::MP::Config ();
41    
42 root 1.2 our $PROTOCOL_VERSION = 0;
43 root 1.1
44 root 1.39 =item $listener = mp_listener $host, $port, <constructor-args>
45 root 1.1
46     Creates a listener on the given host/port using
47     C<AnyEvent::Socket::tcp_server>.
48    
49     See C<new>, below, for constructor arguments.
50    
51 root 1.10 Defaults for peerhost, peerport and fh are provided.
52 root 1.1
53     =cut
54    
55 root 1.46 sub mp_server($$;%) {
56     my ($host, $port, %arg) = @_;
57 root 1.1
58     AnyEvent::Socket::tcp_server $host, $port, sub {
59     my ($fh, $host, $port) = @_;
60    
61 root 1.39 my $tp = new AnyEvent::MP::Transport
62 root 1.1 fh => $fh,
63     peerhost => $host,
64     peerport => $port,
65 root 1.46 %arg,
66 root 1.39 ;
67     $tp->{keepalive} = $tp;
68 root 1.46 }, delete $arg{prepare}
69 root 1.1 }
70    
71 root 1.2 =item $guard = mp_connect $host, $port, <constructor-args>, $cb->($transport)
72    
73     =cut
74    
75     sub mp_connect {
76 root 1.31 my $release = pop;
77 root 1.2 my ($host, $port, @args) = @_;
78    
79 root 1.31 my $state;
80    
81 root 1.45 $state = AnyEvent::Socket::tcp_connect $host, $port, my$x=sub {
82 root 1.2 my ($fh, $nhost, $nport) = @_;
83    
84 root 1.31 return $release->() unless $fh;
85 root 1.2
86 root 1.31 $state = new AnyEvent::MP::Transport
87 root 1.2 fh => $fh,
88     peername => $host,
89     peerhost => $nhost,
90     peerport => $nport,
91 root 1.31 release => $release,
92 root 1.2 @args,
93 root 1.31 ;
94     };
95    
96     \$state
97 root 1.2 }
98    
99 root 1.1 =item new AnyEvent::MP::Transport
100    
101     # immediately starts negotiation
102     my $transport = new AnyEvent::MP::Transport
103 root 1.2 # mandatory
104 root 1.1 fh => $filehandle,
105 root 1.2 local_id => $identifier,
106 root 1.1 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 root 1.2 greeting => { key => value },
113 root 1.1
114     # tls support
115     tls_ctx => AnyEvent::TLS,
116     peername => $peername, # for verification
117     ;
118    
119     =cut
120    
121 root 1.48 sub LATENCY() { 5 } # assumed max. network latency
122 root 1.27
123 root 1.34 our @FRAMINGS = qw(json storable); # the framing types we accept and send, in order of preference
124 root 1.41 our @AUTH_SND = qw(tls_md6_64_256 hmac_md6_64_256); # auth types we send
125     our @AUTH_RCV = (@AUTH_SND, qw(tls_anon cleartext)); # auth types we accept
126 root 1.7
127     #AnyEvent::Handle::register_write_type mp_record => sub {
128     #};
129 root 1.4
130 root 1.1 sub new {
131     my ($class, %arg) = @_;
132    
133     my $self = bless \%arg, $class;
134    
135     $self->{queue} = [];
136    
137     {
138     Scalar::Util::weaken (my $self = $self);
139    
140 root 1.33 my $config = AnyEvent::MP::Config::config;
141 root 1.30
142 root 1.31 my $latency = $config->{network_latency} || LATENCY;
143    
144 root 1.42 $self->{secret} = $config->{secret}
145     unless exists $self->{secret};
146 root 1.2
147 root 1.42 $self->{timeout} = $config->{monitor_timeout} || $AnyEvent::MP::Kernel::MONITOR_TIMEOUT
148     unless exists $self->{timeout};
149 root 1.24
150 root 1.42 $self->{timeout} -= $latency;
151 root 1.31
152 root 1.42 $self->{timeout} = 1 + $latency
153     if $self->{timeout} < 1 + $latency;
154 root 1.27
155 root 1.42 my $secret = $self->{secret};
156 root 1.19
157 root 1.30 if (exists $config->{cert}) {
158 root 1.42 $self->{tls_ctx} = {
159 root 1.19 sslv2 => 0,
160     sslv3 => 0,
161     tlsv1 => 1,
162     verify => 1,
163 root 1.30 cert => $config->{cert},
164     ca_cert => $config->{cert},
165 root 1.19 verify_require_client_cert => 1,
166     };
167     }
168    
169 root 1.1 $self->{hdl} = new AnyEvent::Handle
170 root 1.48 fh => delete $self->{fh},
171     autocork => 1,
172     no_delay => 1,
173     keepalive => 1,
174     on_error => sub {
175 root 1.1 $self->error ($_[2]);
176     },
177 root 1.48 rtimeout => $latency,
178     peername => delete $self->{peername},
179 root 1.1 ;
180    
181 root 1.2 my $greeting_kv = $self->{greeting} ||= {};
182 root 1.24
183 root 1.38 $self->{local_node} ||= $AnyEvent::MP::Kernel::NODE;
184 root 1.24
185 root 1.42 $greeting_kv->{tls} = "1.0" if $self->{tls_ctx};
186 root 1.31 $greeting_kv->{provider} = "AE-$AnyEvent::MP::Kernel::VERSION";
187 root 1.7 $greeting_kv->{peeraddr} = AnyEvent::Socket::format_hostport $self->{peerhost}, $self->{peerport};
188 root 1.42 $greeting_kv->{timeout} = $self->{timeout};
189 root 1.23
190 root 1.1 # send greeting
191 root 1.12 my $lgreeting1 = "aemp;$PROTOCOL_VERSION"
192 root 1.24 . ";$self->{local_node}"
193 root 1.7 . ";" . (join ",", @AUTH_RCV)
194     . ";" . (join ",", @FRAMINGS)
195     . (join "", map ";$_=$greeting_kv->{$_}", keys %$greeting_kv);
196 root 1.12
197 root 1.31 my $lgreeting2 = MIME::Base64::encode_base64 AnyEvent::MP::Kernel::nonce (66), "";
198 root 1.1
199 root 1.7 $self->{hdl}->push_write ("$lgreeting1\012$lgreeting2\012");
200 root 1.1
201     # expect greeting
202 root 1.12 $self->{hdl}->rbuf_max (4 * 1024);
203 root 1.1 $self->{hdl}->push_read (line => sub {
204 root 1.7 my $rgreeting1 = $_[1];
205 root 1.1
206 root 1.26 my ($aemp, $version, $rnode, $auths, $framings, @kv) = split /;/, $rgreeting1;
207 root 1.1
208     if ($aemp ne "aemp") {
209     return $self->error ("unparsable greeting");
210 root 1.12 } elsif ($version != $PROTOCOL_VERSION) {
211     return $self->error ("version mismatch (we: $PROTOCOL_VERSION, they: $version)");
212 root 1.39 } elsif ($rnode eq $self->{local_node}) {
213 root 1.42 AnyEvent::MP::Global::avoid_seed ($self->{seed})
214     if exists $self->{seed};
215    
216 root 1.39 return $self->error ("I refuse to talk to myself");
217     } elsif ($AnyEvent::MP::Kernel::NODE{$rnode} && $AnyEvent::MP::Kernel::NODE{$rnode}{transport}) {
218     return $self->error ("$rnode already connected, not connecting again.");
219 root 1.1 }
220    
221 root 1.2 $self->{remote_node} = $rnode;
222 root 1.1
223 root 1.2 $self->{remote_greeting} = {
224     map /^([^=]+)(?:=(.*))?/ ? ($1 => $2) : (),
225     @kv
226 root 1.1 };
227    
228 root 1.7 # read nonce
229     $self->{hdl}->push_read (line => sub {
230     my $rgreeting2 = $_[1];
231    
232 root 1.19 "$lgreeting1\012$lgreeting2" ne "$rgreeting1\012$rgreeting2" # echo attack?
233     or return $self->error ("authentication error, echo attack?");
234    
235 root 1.41 my $tls = $self->{tls_ctx} && 1 == int $self->{remote_greeting}{tls};
236    
237     my $s_auth;
238     for my $auth_ (split /,/, $auths) {
239     if (grep $auth_ eq $_, @AUTH_SND and ($auth_ !~ /^tls_/ or $tls)) {
240     $s_auth = $auth_;
241     last;
242     }
243     }
244    
245     defined $s_auth
246     or return $self->error ("$auths: no common auth type supported");
247    
248     my $s_framing;
249     for my $framing_ (split /,/, $framings) {
250     if (grep $framing_ eq $_, @FRAMINGS) {
251     $s_framing = $framing_;
252     last;
253     }
254     }
255    
256     defined $s_framing
257     or return $self->error ("$framings: no common framing method supported");
258    
259 root 1.30 my $key;
260 root 1.19 my $lauth;
261    
262 root 1.41 if ($tls) {
263 root 1.8 $self->{tls} = $lgreeting2 lt $rgreeting2 ? "connect" : "accept";
264     $self->{hdl}->starttls ($self->{tls}, $self->{tls_ctx});
265 root 1.41
266     $lauth =
267     $s_auth eq "tls_anon" ? ""
268     : $s_auth eq "tls_md6_64_256" ? Digest::MD6::md6_hex "$lgreeting1\012$lgreeting2\012$rgreeting1\012$rgreeting2\012"
269     : return $self->error ("$s_auth: fatal, selected unsupported snd auth method");
270    
271 root 1.30 } elsif (length $secret) {
272 root 1.41 return $self->error ("$s_auth: fatal, selected unsupported snd auth method")
273     unless $s_auth eq "hmac_md6_64_256"; # hardcoded atm.
274    
275 root 1.30 $key = Digest::MD6::md6 $secret;
276 root 1.19 # we currently only support hmac_md6_64_256
277     $lauth = Digest::HMAC_MD6::hmac_md6_hex $key, "$lgreeting1\012$lgreeting2\012$rgreeting1\012$rgreeting2\012", 64, 256;
278 root 1.41
279 root 1.30 } else {
280     return $self->error ("unable to handshake TLS and no shared secret configured");
281 root 1.8 }
282 root 1.2
283 root 1.7 $self->{hdl}->push_write ("$s_auth;$lauth;$s_framing\012");
284 root 1.2
285 root 1.19 # read the authentication response
286 root 1.7 $self->{hdl}->push_read (line => sub {
287     my ($hdl, $rline) = @_;
288 root 1.2
289 root 1.7 my ($auth_method, $rauth2, $r_framing) = split /;/, $rline;
290 root 1.1
291 root 1.19 my $rauth =
292     $auth_method eq "hmac_md6_64_256" ? Digest::HMAC_MD6::hmac_md6_hex $key, "$rgreeting1\012$rgreeting2\012$lgreeting1\012$lgreeting2\012", 64, 256
293     : $auth_method eq "cleartext" ? unpack "H*", $secret
294 root 1.41 : $auth_method eq "tls_anon" ? ($tls ? "" : "\012\012") # \012\012 never matches
295     : $auth_method eq "tls_md6_64_256" ? ($tls ? Digest::MD6::md6_hex "$rgreeting1\012$rgreeting2\012$lgreeting1\012$lgreeting2\012" : "\012\012")
296     : return $self->error ("$auth_method: fatal, selected unsupported rcv auth method");
297 root 1.19
298 root 1.7 if ($rauth2 ne $rauth) {
299     return $self->error ("authentication failure/shared secret mismatch");
300     }
301 root 1.1
302 root 1.7 $self->{s_framing} = $s_framing;
303 root 1.2
304 root 1.7 $hdl->rbuf_max (undef);
305 root 1.1
306 root 1.27 $self->{hdl}->rtimeout ($self->{remote_greeting}{timeout});
307 root 1.42 $self->{hdl}->wtimeout ($self->{timeout} - LATENCY);
308 root 1.36 $self->{hdl}->on_wtimeout (sub { $self->send ([]) });
309 root 1.24
310 root 1.47 my $queue = delete $self->{queue}; # we are connected
311    
312 root 1.7 $self->connected;
313 root 1.1
314 root 1.27 # send queued messages
315 root 1.23 $self->send ($_)
316 root 1.7 for @$queue;
317 root 1.1
318 root 1.27 # receive handling
319     my $src_node = $self->{node};
320 root 1.45 my $rmsg; $rmsg = $self->{rmsg} = sub {
321 root 1.7 $_[0]->push_read ($r_framing => $rmsg);
322 root 1.1
323 root 1.31 local $AnyEvent::MP::Kernel::SRCNODE = $src_node;
324     AnyEvent::MP::Kernel::_inject (@{ $_[1] });
325 root 1.7 };
326     $hdl->push_read ($r_framing => $rmsg);
327 root 1.45
328     Scalar::Util::weaken $rmsg;
329     Scalar::Util::weaken $src_node;
330 root 1.7 });
331 root 1.1 });
332     });
333     }
334    
335     $self
336     }
337    
338     sub error {
339     my ($self, $msg) = @_;
340    
341 root 1.39 delete $self->{keepalive};
342    
343 root 1.40 # $AnyEvent::MP::Kernel::WARN->(9, "$self->{peerhost}:$self->{peerport} $msg");#d#
344 root 1.39
345     $self->{node}->transport_error (transport_error => $self->{node}{id}, $msg)
346 root 1.31 if $self->{node} && $self->{node}{transport} == $self;
347    
348     (delete $self->{release})->()
349     if exists $self->{release};
350    
351 root 1.37 # $AnyEvent::MP::Kernel::WARN->(7, "$self->{peerhost}:$self->{peerport}: $msg");
352 root 1.4 $self->destroy;
353 root 1.1 }
354    
355 root 1.2 sub connected {
356     my ($self) = @_;
357    
358 root 1.39 delete $self->{keepalive};
359    
360 root 1.31 (delete $self->{release})->()
361     if exists $self->{release};
362 root 1.23
363 root 1.39 $AnyEvent::MP::Kernel::WARN->(9, "$self->{peerhost}:$self->{peerport} connected as $self->{remote_node}");
364    
365 root 1.31 my $node = AnyEvent::MP::Kernel::add_node ($self->{remote_node});
366 root 1.4 Scalar::Util::weaken ($self->{node} = $node);
367 root 1.31 $node->transport_connect ($self);
368 root 1.2 }
369    
370 root 1.1 sub send {
371 root 1.2 $_[0]{hdl}->push_write ($_[0]{s_framing} => $_[1]);
372 root 1.1 }
373    
374     sub destroy {
375     my ($self) = @_;
376    
377 root 1.42 (delete $self->{release})->()
378     if exists $self->{release};
379    
380 root 1.2 $self->{hdl}->destroy
381     if $self->{hdl};
382 root 1.1 }
383    
384     sub DESTROY {
385     my ($self) = @_;
386    
387     $self->destroy;
388     }
389    
390     =back
391    
392 root 1.7 =head1 PROTOCOL
393    
394 root 1.43 The AEMP protocol is relatively simple, and consists of three phases which
395     are symmetrical for both sides: greeting (followed by optionally switching
396     to TLS mode), authentication and packet exchange.
397 root 1.7
398 root 1.43 The protocol is designed to allow both full-text and binary streams.
399 root 1.7
400     The greeting consists of two text lines that are ended by either an ASCII
401     CR LF pair, or a single ASCII LF (recommended).
402    
403     =head2 GREETING
404    
405 root 1.15 All the lines until after authentication must not exceed 4kb in length,
406 root 1.43 including line delimiter. Afterwards there is no limit on the packet size
407     that can be received.
408 root 1.15
409     =head3 First Greeting Line
410 root 1.12
411 root 1.16 Example:
412    
413 root 1.43 aemp;0;rain;tls_md6_64_256,hmac_md6_64_256,tls_anon,cleartext;json,storable;timeout=12;peeraddr=10.0.0.1:48082
414 root 1.16
415     The first line contains strings separated (not ended) by C<;>
416 root 1.43 characters. The first five strings are fixed by the protocol, the
417 root 1.16 remaining strings are C<KEY=VALUE> pairs. None of them may contain C<;>
418 root 1.43 characters themselves (when escaping is needed, use C<%3b> to represent
419     C<;> and C<%25> to represent C<%>)-
420 root 1.16
421 root 1.12 The fixed strings are:
422 root 1.7
423     =over 4
424    
425 root 1.18 =item protocol identification
426 root 1.7
427 root 1.43 The constant C<aemp> to identify this protocol.
428 root 1.7
429     =item protocol version
430    
431 root 1.12 The protocol version supported by this end, currently C<0>. If the
432     versions don't match then no communication is possible. Minor extensions
433 root 1.18 are supposed to be handled through additional key-value pairs.
434 root 1.7
435 root 1.43 =item the node ID
436 root 1.7
437 root 1.39 This is the node ID of the connecting node.
438 root 1.7
439     =item the acceptable authentication methods
440    
441     A comma-separated list of authentication methods supported by the
442     node. Note that AnyEvent::MP supports a C<hex_secret> authentication
443 root 1.43 method that accepts a clear-text password (hex-encoded), but will not use
444     this authentication method itself.
445 root 1.7
446 root 1.43 The receiving side should choose the first authentication method it
447     supports.
448 root 1.7
449     =item the acceptable framing formats
450    
451 root 1.43 A comma-separated list of packet encoding/framing formats understood. The
452 root 1.7 receiving side should choose the first framing format it supports for
453     sending packets (which might be different from the format it has to accept).
454    
455 root 1.10 =back
456 root 1.8
457     The remaining arguments are C<KEY=VALUE> pairs. The following key-value
458     pairs are known at this time:
459    
460     =over 4
461    
462 root 1.43 =item timeout=<seconds>
463    
464     The amount of time after which this node should be detected as dead unless
465     some data has been received. The node is responsible to send traffic
466 root 1.48 reasonably more often than this interval (such as every timeout minus
467     five seconds).
468 root 1.43
469 root 1.8 =item provider=<module-version>
470    
471     The software provider for this implementation. For AnyEvent::MP, this is
472     C<AE-0.0> or whatever version it currently is at.
473    
474     =item peeraddr=<host>:<port>
475    
476 root 1.39 The peer address (socket address of the other side) as seen locally.
477 root 1.8
478     =item tls=<major>.<minor>
479    
480     Indicates that the other side supports TLS (version should be 1.0) and
481     wishes to do a TLS handshake.
482    
483     =back
484    
485 root 1.15 =head3 Second Greeting Line
486    
487 root 1.8 After this greeting line there will be a second line containing a
488     cryptographic nonce, i.e. random data of high quality. To keep the
489     protocol text-only, these are usually 32 base64-encoded octets, but
490     it could be anything that doesn't contain any ASCII CR or ASCII LF
491     characters.
492    
493 root 1.14 I<< The two nonces B<must> be different, and an aemp implementation
494     B<must> check and fail when they are identical >>.
495    
496 root 1.43 Example of a nonce line (yes, it's random-looking because it is random
497     data):
498 root 1.8
499 root 1.43 2XYhdG7/O6epFa4wuP0ujAEx1rXYWRcOypjUYK7eF6yWAQr7gwIN9m/2+mVvBrTPXz5GJDgfGm9d8QRABAbmAP/s
500 root 1.8
501     =head2 TLS handshake
502    
503 root 1.14 I<< If, after the handshake, both sides indicate interest in TLS, then the
504 root 1.43 connection B<must> use TLS, or fail to continue. >>
505 root 1.8
506     Both sides compare their nonces, and the side who sent the lower nonce
507     value ("string" comparison on the raw octet values) becomes the client,
508     and the one with the higher nonce the server.
509    
510     =head2 AUTHENTICATION PHASE
511    
512     After the greeting is received (and the optional TLS handshake),
513     the authentication phase begins, which consists of sending a single
514     C<;>-separated line with three fixed strings and any number of
515     C<KEY=VALUE> pairs.
516    
517     The three fixed strings are:
518    
519     =over 4
520    
521     =item the authentication method chosen
522    
523     This must be one of the methods offered by the other side in the greeting.
524    
525 root 1.41 Note that all methods starting with C<tls_> are only valid I<iff> TLS was
526     successfully handshaked (and to be secure the implementation must enforce
527     this).
528    
529 root 1.13 The currently supported authentication methods are:
530    
531     =over 4
532    
533     =item cleartext
534    
535     This is simply the shared secret, lowercase-hex-encoded. This method is of
536 root 1.43 course very insecure if TLS is not used (and not completely secure even
537     if TLS is used), which is why this module will accept, but not generate,
538     cleartext auth replies.
539 root 1.13
540     =item hmac_md6_64_256
541    
542 root 1.43 This method uses an MD6 HMAC with 64 bit blocksize and 256 bit hash, and
543     requires a shared secret. It is the preferred auth method when a shared
544     secret is available.
545    
546     First, the shared secret is hashed with MD6:
547 root 1.13
548     key = MD6 (secret)
549    
550     This secret is then used to generate the "local auth reply", by taking
551     the two local greeting lines and the two remote greeting lines (without
552     line endings), appending \012 to all of them, concatenating them and
553 root 1.43 calculating the MD6 HMAC with the key:
554 root 1.13
555     lauth = HMAC_MD6 key, "lgreeting1\012lgreeting2\012rgreeting1\012rgreeting2\012"
556    
557     This authentication token is then lowercase-hex-encoded and sent to the
558     other side.
559    
560     Then the remote auth reply is generated using the same method, but local
561     and remote greeting lines swapped:
562    
563     rauth = HMAC_MD6 key, "rgreeting1\012rgreeting2\012lgreeting1\012lgreeting2\012"
564    
565     This is the token that is expected from the other side.
566    
567 root 1.41 =item tls_anon
568 root 1.19
569 root 1.43 This type is only valid I<iff> TLS was enabled and the TLS handshake
570 root 1.19 was successful. It has no authentication data, as the server/client
571     certificate was successfully verified.
572    
573 root 1.43 This authentication type is somewhat insecure, as it allows a
574     man-in-the-middle attacker to change some of the connection parameters
575     (such as the framing format), although there is no known attack that
576     exploits this in a way that is worse than just denying the service.
577 root 1.41
578 root 1.43 By default, this implementation accepts but never generates this auth
579     reply.
580 root 1.41
581     =item tls_md6_64_256
582    
583 root 1.43 This type is only valid I<iff> TLS was enabled and the TLS handshake was
584     successful.
585 root 1.41
586     This authentication type simply calculates:
587    
588     lauth = MD6 "rgreeting1\012rgreeting2\012lgreeting1\012lgreeting2\012"
589    
590     and lowercase-hex encodes the result and sends it as authentication
591     data. No shared secret is required (authentication is done by TLS). The
592 root 1.43 checksum exists only to make tinkering with the greeting hard.
593 root 1.19
594 root 1.13 =back
595    
596 root 1.8 =item the authentication data
597    
598 root 1.13 The authentication data itself, usually base64 or hex-encoded data, see
599     above.
600 root 1.8
601     =item the framing protocol chosen
602    
603     This must be one of the framing protocols offered by the other side in the
604 root 1.43 greeting. Each side must accept the choice of the other side, and generate
605     packets in the format it chose itself.
606 root 1.8
607     =back
608    
609 root 1.16 Example of an authentication reply:
610 root 1.9
611 root 1.13 hmac_md6_64_256;363d5175df38bd9eaddd3f6ca18aa1c0c4aa22f0da245ac638d048398c26b8d3;json
612 root 1.9
613 root 1.8 =head2 DATA PHASE
614    
615     After this, packets get exchanged using the chosen framing protocol. It is
616     quite possible that both sides use a different framing protocol.
617    
618 root 1.16 =head2 FULL EXAMPLE
619    
620 root 1.17 This is an actual protocol dump of a handshake, followed by a single data
621 root 1.16 packet. The greater than/less than lines indicate the direction of the
622     transfer only.
623    
624 root 1.43 > 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
625     > yLgdG1ov/02shVkVQer3wzeuywZK+oraTdEQBmIqWHaegxSGDG4g+HqogLQbvdypFOsoDWJ1Sh4ImV4DMhvUBwTK
626    
627     < 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
628     < +xMQXP8ElfNmuvEhsmcp+s2wCJOuQAsPxSg3d2Ewhs6gBnJz+ypVdWJ/wAVrXqlIJfLeVS/CBy4gEGkyWHSuVb1L
629    
630     > hmac_md6_64_256;5ad913855742ae5a03a5aeb7eafa4c78629de136bed6acd73eea36c9e98df44a;json
631    
632     < hmac_md6_64_256;84cd590976f794914c2ca26dac3a207a57a6798b9171289c114de07cf0c20401;json
633     < ["","AnyEvent::MP::_spawn","57Cs1CggVJjzYaQp13XXg4.c","AnyEvent::MP::Global::connect",0,"anon/57Cs1CggVJjzYaQp13XXg4"]
634     ...
635    
636     The shared secret in use was C<8ugxrtw6H5tKnfPWfaSr4HGhE8MoJXmzTT1BWq7sLutNcD0IbXprQlZjIbl7MBKoeklG3IEfY9GlJthC0pENzk>.
637 root 1.16
638 root 1.1 =head1 SEE ALSO
639    
640 root 1.29 L<AnyEvent::MP>.
641 root 1.1
642     =head1 AUTHOR
643    
644     Marc Lehmann <schmorp@schmorp.de>
645     http://home.schmorp.de/
646    
647     =cut
648    
649     1
650