File Coverage

blib/lib/IO/Stream/MatrixSSL.pm
Criterion Covered Total %
statement 103 137 75.1
branch 41 68 60.2
condition 5 26 19.2
subroutine 14 15 93.3
pod 1 3 33.3
total 164 249 65.8


line stmt bran cond sub pod time code
1             package IO::Stream::MatrixSSL;
2 9     9   1113463 use 5.010001;
  9         63  
3 9     9   39 use warnings;
  9         15  
  9         216  
4 9     9   35 use strict;
  9         36  
  9         154  
5 9     9   569 use utf8;
  9         24  
  9         74  
6 9     9   224 use Carp;
  9         13  
  9         635  
7              
8             our $VERSION = 'v2.0.2';
9              
10 9     9   422 use IO::Stream::const;
  9         6543  
  9         50  
11 9     9   3012 use IO::Stream::MatrixSSL::const;
  9         23  
  9         53  
12 9     9   4275 use Crypt::MatrixSSL3 qw( :all );
  9         191495  
  9         43  
13              
14 9     9   11385 use IO::Stream::MatrixSSL::Client;
  9         20  
  9         239  
15 9     9   3139 use IO::Stream::MatrixSSL::Server;
  9         20  
  9         7552  
16              
17              
18             sub stream {
19 0     0 1 0 my ($self) = @_;
20 0         0 my $stream = $self;
21 0         0 while ($stream->{_master}) {
22 0         0 $stream = $stream->{_master};
23             }
24 0         0 return $stream;
25             }
26              
27             sub T {
28 4     4 0 16 my ($self) = @_;
29 4         39 my $m = $self->{_master};
30 4         29 $m->EVENT(0, ETOHANDSHAKE);
31 4         5015 return;
32             }
33              
34             sub WRITE {
35 14     14   5941 my ($self) = @_;
36 14         28 my $m = $self->{_master};
37 14 50       88 if ($self->{_closed}) {
    100          
    50          
38 0         0 $m->EVENT(0, 'ssl closed: closure alert or fatal alert was sent');
39             }
40             elsif (!$self->{_handshaked}) {
41 7         15 $self->{_want_write} = 1;
42             }
43             elsif (!$self->{_want_close}) {
44 7   50     32 my $s = substr $m->{out_buf}, $m->{out_pos}||0;
45 7         15 my $n = length $s;
46             ENCODE:
47 7         15 while (length $s) {
48 7         17 my $s2 = substr $s, 0, SSL_MAX_PLAINTEXT_LEN, q{};
49 7         74 my $rc = $self->{_ssl}->encode_to_outdata($s2);
50 7 50       18 return $m->EVENT(0, 'ssl error: '.get_ssl_error($rc)) if $rc <= 0;
51 7         41 while (my $bytes = $self->{_ssl}->get_outdata($self->{out_buf})) {
52 7         18 $rc = $self->{_ssl}->sent_data($bytes);
53 7 50       22 last if $rc == PS_SUCCESS;
54 0 0       0 next if $rc == MATRIXSSL_REQUEST_SEND;
55 0 0       0 next if $rc == MATRIXSSL_HANDSHAKE_COMPLETE;
56 0 0       0 if ($rc == MATRIXSSL_REQUEST_CLOSE) {
57 0         0 $self->{_want_close} = 1;
58             # XXX Will report to $m "{out_buf} was completely sent"
59             # while is may be only partially sent.
60 0         0 last ENCODE;
61             }
62 0         0 return $m->EVENT(0, 'ssl error: '.get_ssl_error($rc));
63             }
64             }
65 7 50       18 if (defined $m->{out_pos}) {
66 0         0 $m->{out_pos} += $n;
67             } else {
68 7         10 $m->{out_buf} = q{};
69             }
70 7         12 $m->{out_bytes} += $n;
71 7         23 $m->EVENT(OUT);
72 7         77 $self->{_slave}->WRITE();
73             }
74 14         102 return;
75             }
76              
77             sub EVENT { ## no critic (ProhibitExcessComplexity)
78 57     57 0 86069 my ($self, $e, $err) = @_;
79 57         103 my $m = $self->{_master};
80 57 50 66     205 if ($e & SENT && $self->{_want_close}) {
81 0         0 $self->{_closed} = 1;
82 0   0     0 $err ||= 'ssl closed: closure alert or fatal alert was sent';
83             }
84 57         88 $e &= ~OUT;
85 57 100       122 if (!$self->{_handshaked}) {
86 26         38 $e &= ~SENT;
87             }
88 57 50 66     127 return if !$e && !$err;
89 51 100       98 if ($e & IN) {
90 29         41 $e &= ~IN;
91 29         43 RECV:
92             my @warnings;
93 29         61 while (length $self->{in_buf}) {
94 60         57754 my $rc = $self->{_ssl}->received_data($self->{in_buf}, my $buf);
95 103 100       7724 RC:
96             last if $rc == PS_SUCCESS;
97 87 100       169 next if $rc == MATRIXSSL_REQUEST_RECV;
98 51 100       95 next if $rc == MATRIXSSL_REQUEST_SEND;
99 44 100       79 if ($rc == MATRIXSSL_HANDSHAKE_COMPLETE) {
100 1         8 $self->_handshaked();
101 1         3 next;
102             }
103 43 50       92 if ($rc == MATRIXSSL_RECEIVED_ALERT) {
    50          
    0          
104 0         0 my ($level, $descr) = get_ssl_alert($buf);
105 0 0       0 if ($level == SSL_ALERT_LEVEL_FATAL) {
106 0         0 $self->{_ssl}->processed_data($buf);
107 0   0     0 $err ||= "ssl fatal alert: $descr";
108 0         0 last;
109             }
110 0 0       0 if ($descr != SSL_ALERT_CLOSE_NOTIFY) {
111 0         0 push @warnings, $descr;
112             }
113             }
114             elsif ($rc == MATRIXSSL_APP_DATA) {
115 43         95 $self->_handshaked();
116 43         54 $e |= IN;
117 43         175 $m->{in_buf} .= $buf;
118 43         66 $m->{in_bytes} += length $buf;
119             }
120             elsif ($rc == MATRIXSSL_APP_DATA_COMPRESSED) {
121 0         0 $self->_handshaked();
122 0   0     0 $err ||= 'ssl error: not implemented because USE_ZLIB_COMPRESSION should not be enabled';
123 0         0 last;
124             }
125             else {
126 0   0     0 $err ||= 'ssl error: '.get_ssl_error($rc);
127 0         0 last;
128             }
129 43         135 $rc = $self->{_ssl}->processed_data($buf);
130 43         84 goto RC;
131             }
132 29 50       63 if (@warnings) {
133             # XXX warning alert(s) may be lost if some other error or
134             # fatal alert happens after warning alert(s).
135 0   0     0 $err ||= join q{ }, 'ssl warning alert:', @warnings;
136             }
137             SEND:
138 29         144 while (my $bytes = $self->{_ssl}->get_outdata($self->{out_buf})) {
139 7         30 my $rc = $self->{_ssl}->sent_data($bytes);
140 7 100       21 last if $rc == PS_SUCCESS;
141 2 50       7 next if $rc == MATRIXSSL_REQUEST_SEND;
142 2 50       7 if ($rc == MATRIXSSL_HANDSHAKE_COMPLETE) {
143 2         14 $self->_handshaked();
144 2         9 next;
145             }
146 0 0       0 if ($rc == MATRIXSSL_REQUEST_CLOSE) {
147 0         0 $self->{_want_close} = 1;
148 0         0 last;
149             }
150 0   0     0 $err ||= 'ssl error: '.get_ssl_error($rc);
151 0         0 last;
152             }
153 29 100       59 if (length $self->{out_buf}) {
154 5         22 $self->{_slave}->WRITE();
155             }
156             }
157 51 100       154 if ($e & RESOLVED) {
158 5         32 $m->{ip} = $self->{ip};
159             }
160 51 100       100 if ($e & EOF) {
161 5         13 $m->{is_eof} = $self->{is_eof};
162 5 50       18 if (!$self->{_handshaked}) {
163 0   0     0 $err ||= 'ssl handshake error: unexpected EOF';
164             }
165             }
166 51 100       86 if ($e & CONNECTED) {
167 5         62 $self->{_t} = EV::timer(TOHANDSHAKE, 0, $self->{_cb_t});
168             }
169 51         195 $m->EVENT($e, $err);
170 49         9088 return;
171             }
172              
173             sub _handshaked {
174 46     46   68 my ($self) = @_;
175 46 100       79 if (!$self->{_handshaked}) {
176 5         9 $self->{_handshaked} = 1;
177 5         23 undef $self->{_t};
178 5 100       12 if ($self->{_want_write}) {
179 3         11 $self->WRITE();
180             }
181             }
182 46         67 return;
183             }
184              
185              
186             1; # Magic true value required at end of module
187             __END__