File Coverage

blib/lib/IO/Stream/MatrixSSL/Client.pm
Criterion Covered Total %
statement 50 50 100.0
branch 8 12 66.6
condition 1 2 50.0
subroutine 14 14 100.0
pod 1 2 50.0
total 74 80 92.5


line stmt bran cond sub pod time code
1             package IO::Stream::MatrixSSL::Client;
2 9     9   149 use 5.010001;
  9         28  
3 9     9   37 use warnings;
  9         13  
  9         322  
4 9     9   36 use strict;
  9         13  
  9         151  
5 9     9   33 use utf8;
  9         13  
  9         109  
6 9     9   200 use Carp;
  9         16  
  9         680  
7              
8             our $VERSION = 'v2.0.2';
9              
10 9     9   50 use IO::Stream::const;
  9         33  
  9         70  
11 9     9   1277 use IO::Stream::MatrixSSL::const;
  9         15  
  9         46  
12 9     9   45 use Crypt::MatrixSSL3 qw( :all );
  9         15  
  9         40  
13 9     9   8016 use Scalar::Util qw( weaken );
  9         15  
  9         391  
14              
15 9     9   442 use parent qw( -norequire IO::Stream::MatrixSSL );
  9         234  
  9         52  
16              
17              
18             sub new {
19 5     5 1 3734 my ($class, $opt) = @_;
20             my $self = bless {
21             crt => undef, # filename(s) with client's certificate(s)
22             key => undef, # filename with client's private key
23             pass => undef, # password to decrypt private key
24             trusted_CA => $Crypt::MatrixSSL3::CA_CERTIFICATES, # filename(s) with trusted root CA cert(s)
25             cb => undef, # callback for validating certificate
26 5   50     19 %{$opt // {}},
  5         90  
27             out_buf => q{}, # modified on: OUT
28             out_pos => undef, # modified on: OUT
29             out_bytes => 0, # modified on: OUT
30             in_buf => q{}, # modified on: IN
31             in_bytes => 0, # modified on: IN
32             ip => undef, # modified on: RESOLVED
33             is_eof => undef, # modified on: EOF
34             # TODO Make this field public and add feature 'restore session'.
35             # _ssl_session=> undef, # MatrixSSL 'sessionId' object
36             _ssl => undef, # MatrixSSL 'session' object
37             _ssl_keys => undef, # MatrixSSL 'keys' object
38             _handshaked => 0, # flag, will be true after handshake
39             _want_write => 0, # flag, will be true if write() was called before handshake
40             _want_close => 0, # flag, will be true after generating MATRIXSSL_REQUEST_CLOSE
41             _closed => 0, # flag, will be true after sending MATRIXSSL_REQUEST_CLOSE
42             _t => undef,
43             _cb_t => undef,
44             }, $class;
45 5         26 weaken(my $this = $self);
46 5 50   2   41 $self->{_cb_t} = sub { $this && $this->T() };
  2         99242  
47             my $cb = !$self->{cb} ? undef : sub {
48 2 50   2   17 $this ? $this->{cb}->($this, @_) : CERTVALIDATOR_INTERNAL_ERROR
49 5 100       24 };
50             # Initialize SSL.
51             # TODO OPTIMIZATION Cache {_ssl_keys}.
52 5         38 $self->{_ssl_keys} = Crypt::MatrixSSL3::Keys->new();
53             my $rc = $self->{_ssl_keys}->load_rsa(
54             $self->{crt}, $self->{key}, $self->{pass}, $self->{trusted_CA}
55 5         32046 );
56 5 50       56 croak 'ssl error: '.get_ssl_error($rc) if $rc != PS_SUCCESS;
57             # TODO OPTIMIZATION Use {_ssl_session}.
58             # TODO Add feature: let user provide @cipherSuites.
59             # TODO Add feature: let user provide $expectedName.
60             $self->{_ssl} = Crypt::MatrixSSL3::Client->new(
61 5         65 $self->{_ssl_keys}, undef, undef, $cb, undef, undef, undef
62             );
63 5         486 $rc = $self->{_ssl}->sent_data( $self->{_ssl}->get_outdata($self->{out_buf}) );
64 5 50       25 croak 'ssl error: '.get_ssl_error($rc) if $rc != PS_SUCCESS;
65 5         64 return $self;
66             }
67              
68             sub PREPARE {
69 5     5 0 767 my ($self, $fh, $host, $port) = @_;
70 5 100       17 if (!defined $host) { # ... else timer will be set on CONNECTED
71 1         11 $self->{_t} = EV::timer(TOHANDSHAKE, 0, $self->{_cb_t});
72             }
73 5         25 $self->{_slave}->PREPARE($fh, $host, $port);
74 5         5744 $self->{_slave}->WRITE(); # output 'client hello'
75 5         33 return;
76             }
77              
78              
79             1;