use Net::SSLeay qw( die_now die_if_ssl_error );
Net::SSLeay::load_error_strings();
eval 'no warnings "redefine";
sub Net::SSLeay::load_error_strings () {}
'; die $@ if $@;
Net::SSLeay::SSLeay_add_ssl_algorithms();
eval 'no warnings "redefine";
sub Net::SSLeay::SSLeay_add_ssl_algorithms () {}
'; die $@ if $@;
Net::SSLeay::ENGINE_load_builtin_engines();
eval 'no warnings "redefine";
sub Net::SSLeay::ENGINE_load_builtin_engines () {}
'; die $@ if $@;
Net::SSLeay::ENGINE_register_all_complete();
eval 'no warnings "redefine";
sub Net::SSLeay::ENGINE_register_all_complete () {}
'; die $@ if $@;
Net::SSLeay::randomize();
eval 'no warnings "redefine";
sub Net::SSLeay::randomize (;$$) {}
'; die $@ if $@;
####
my $socket = IO::Socket::INET->new(
PeerAddr => $host,
PeerPort => 'https(443)',
AutoFlush => 1,
Blocking => 0,
Proto => 'tcp' ) or die "can't connect to https server";
####
my $ctx = Net::SSLeay::CTX_new()
or die("Failed to create SSL_CTX $!");
Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_ALL)
and ssl_check_die("ssl ctx set options");
my $ssl = Net::SSLeay::new($ctx)
or die_now("Failed to create SSL $!");
####
sub ssl_get_error {
my $errors = "";
my $errnos = [];
while(my $errno = Net::SSLeay::ERR_get_error()) {
push @$errnos, $errno;
$errors .= Net::SSLeay::ERR_error_string($errno) . "\n";
}
return $errors, $errnos if wantarray;
return $errors;
}
sub ssl_check_die {
my ($message) = @_;
my ($errors, $errnos) = ssl_get_error();
die "${message}: ${errors}" if @$errnos;
return;
}
####
Net::SSLeay::set_fd($ssl, fileno($socket));
my $res = Net::SSLeay::connect($ssl)
and Net::SSLeay::die_if_ssl_error("ssl connect");
if($res < 0){
# Here the connect failed because the exchange is not complete;
# continue to select on this socket and retry every time the
# socket selects true until it succeeds.
return;
} else {
# Here the connect is complete. This is where to but the code
# that changes the "select" handler for the socket for the next
# phase (writing the data).
}
####
my $written = $ssl->write(substr($cur_buff, $cur_count));
if($written <= 0){
unless($! eq "Resource temporarily unavailable"){
## An error has occurred - recovery code goes here
}
return;
}
$cur_count += $written;
if($cur_count == length($cur_buff)){
$cur_count = 0;
$cur_buff = undef;
### We have emptied the current buffer
### Here is where code specific to select dispatcher
### must determine whether we have written all the data...
}
####
my $res = CORE::shutdown $socket, 1;
####
my $rb = $ssl->read(16384);
ssl_check_die("SSL read");
if(undefined($rb) or length($rb) <= 0){
unless($! eq "Resource temporarily unavailable"){
## Here we are done - do whatever is necessary to
## shutdown select dispatcher and close sockets, release
## ssl and context
}
if($rb){
## you have read some data in $rb -- do something with it
}
}
####
Net::SSLeay::free($ssl);
Net::SSLeay::CTX_free($ctx);
$socket->close();