File Coverage

blib/lib/Net/APNS/Persistent/Base.pm
Criterion Covered Total %
statement 18 86 20.9
branch 0 28 0.0
condition 0 11 0.0
subroutine 6 15 40.0
pod 1 3 33.3
total 25 143 17.4


line stmt bran cond sub pod time code
1             package Net::APNS::Persistent::Base;
2              
3 7     7   118 use 5.008;
  7         21  
  7         640  
4 7     7   39 use strict;
  7         14  
  7         206  
5 7     7   34 use warnings;
  7         12  
  7         418  
6              
7             our $VERSION = '0.01';
8              
9 7     7   34 use base 'Class::Accessor';
  7         13  
  7         7896  
10              
11 7     7   29634 use Net::SSLeay qw(die_now die_if_ssl_error);
  7         171544  
  7         4011  
12 7     7   136 use Socket;
  7         14  
  7         12279  
13              
14             __PACKAGE__->mk_accessors(qw(
15             cert
16             key
17             key_type
18             cert_type
19             passwd
20             _host
21             host_production
22             host_sandbox
23             port
24             sandbox
25             __connection
26             ));
27              
28             my %defaults = (
29             key_type => &Net::SSLeay::FILETYPE_PEM,
30             cert_type => &Net::SSLeay::FILETYPE_PEM,
31             );
32              
33             =head1 NAME
34              
35             Net::APNS::Persistent::Base - Base class for Net::APNS::Persistent and Net::APNS::Feedback
36              
37             =head1 SYNOPSIS
38              
39             See L and L.
40              
41             =head1 DESCRIPTION
42              
43             Base methods for L and L.
44              
45             =cut
46              
47             sub new {
48 0     0 1   my ($class, $init_vals) = @_;
49              
50 0   0       $init_vals ||= {};
51              
52 0           my $self = $class->SUPER::new({
53              
54             %defaults,
55            
56 0           %{$init_vals}
57             });
58              
59             # Use TLSv1
60 0           $Net::SSLeay::ssl_version = 10;
61              
62 0           Net::SSLeay::load_error_strings();
63 0           Net::SSLeay::SSLeay_add_ssl_algorithms();
64 0           Net::SSLeay::randomize();
65            
66 0           return $self;
67             }
68              
69             sub host {
70 0     0 0   my $self = shift;
71              
72 0 0 0       if (@_ || $self->_host) {
73 0           return $self->_host(@_);
74             }
75              
76 0 0         if ($self->sandbox) {
77 0           return $self->host_sandbox;
78             } else {
79 0           return $self->host_production;
80             }
81             }
82              
83             sub _server_sockadder_in {
84 0     0     my $self = shift;
85              
86 0 0         my $ip = inet_aton( $self->host )
87             or die "Unable to get address for " . $self->host;
88              
89 0           return sockaddr_in( $self->port, $ip );
90             }
91              
92             sub _connection {
93 0     0     my $self = shift;
94            
95 0           my $connection = $self->__connection;
96              
97 0           my ($socket, $ctx, $ssl);
98 0 0         ($socket, $ctx, $ssl) = @{$connection}
  0            
99             if $connection;
100            
101             # TODO: attempt reconnect if the socket is bad
102             # at the moment, will just die which is ok since
103             # we only promise to raise an exception in the doccs.
104 0 0 0       if (!$socket || !$ctx || !$ssl) {
      0        
105            
106             # free any existing resources
107 0           $self->disconnect;
108            
109 0 0         socket( $socket, PF_INET, SOCK_STREAM, getprotobyname('tcp'))
110             or die "error creating socket: $!";
111              
112 0 0         connect( $socket, $self->_server_sockadder_in )
113             or die "error connecting socket: $!";
114              
115 0 0         $ctx = Net::SSLeay::CTX_new()
116             or die_now( "failed to create SSL_CTX: $!");
117              
118 0           Net::SSLeay::CTX_set_options( $ctx, &Net::SSLeay::OP_ALL );
119 0           die_if_ssl_error("error while setting ctx options: $!");
120              
121 0     0     Net::SSLeay::CTX_set_default_passwd_cb( $ctx, sub { $self->passwd } );
  0            
122 0           Net::SSLeay::CTX_use_RSAPrivateKey_file( $ctx, $self->key, $self->key_type );
123 0           die_if_ssl_error("error while setting private key: $!");
124              
125 0           Net::SSLeay::CTX_use_certificate_file( $ctx, $self->cert, $self->cert_type );
126 0           die_if_ssl_error("error while setting certificate: $!");
127              
128 0           $ssl = Net::SSLeay::new( $ctx );
129              
130 0           Net::SSLeay::set_fd( $ssl, fileno($socket) );
131 0 0         Net::SSLeay::connect( $ssl )
132             or die_now( "failed ssl connect: $!");
133              
134 0           $connection = [$socket, $ctx, $ssl];
135            
136 0           $self->__connection($connection);
137             }
138              
139 0           return $connection;
140             }
141              
142             sub disconnect {
143 0     0 0   my $self = shift;
144            
145             # go straight to the accessor, we don't
146             # want to create a connection simply to
147             # disconnect it!
148 0           my $connection = $self->__connection;
149              
150 0 0         if (!$connection) {
151 0           return 1;
152             }
153              
154 0           my ($socket, $ctx, $ssl) = @{$connection};
  0            
155              
156 0 0         CORE::shutdown( $socket, 1 )
157             if $socket;
158            
159 0 0         Net::SSLeay::free( $ssl )
160             if $ssl;
161            
162 0 0         Net::SSLeay::CTX_free( $ctx )
163             if $ctx;
164            
165 0 0         close($socket)
166             if $socket;
167              
168 0           $self->__connection(undef);
169              
170 0           return 1;
171             }
172              
173             sub _send {
174 0     0     my ($self, $data) = @_;
175            
176 0           my ($socket, $ctx, $ssl) = @{$self->_connection};
  0            
177              
178 0           Net::SSLeay::ssl_write_all( $ssl, $data );
179 0           die_if_ssl_error("error writing to ssl connection: $!");
180              
181 0           return 1;
182             }
183              
184             sub _read {
185 0     0     my $self = shift;
186              
187 0           my ($socket, $ctx, $ssl) = @{$self->_connection};
  0            
188              
189 0           my $data = Net::SSLeay::ssl_read_all( $ssl );
190 0           die_if_ssl_error("error reading from ssl connection: $!");
191              
192 0           return $data;
193             }
194              
195             sub DESTROY {
196 0     0     my $self = shift;
197              
198 0           $self->disconnect;
199             }
200              
201              
202              
203             =head1 SEE ALSO
204              
205             =over 4
206              
207             =item L
208              
209             =item L.
210              
211             =item L
212              
213             =back
214              
215             =head1 AUTHOR
216              
217             Mark Aufflick, Eaufflick@localE
218              
219             =head1 COPYRIGHT AND LICENSE
220              
221             Copyright (C) 2009 by Mark Aufflick
222              
223             This library is free software; you can redistribute it and/or modify
224             it under the same terms as Perl itself, either Perl version 5.8.9 or,
225             at your option, any later version of Perl 5 you may have available.
226              
227             =cut
228              
229             1;