use warnings;
use strict;
use IO::Socket::SSL;
use constant { BUFSIZE => 16384 };
die 'Invalid BUFSIZE value (must be a multiple of 16)' if(BUFSIZE%16);
my $LOCAL_ADDR='0.0.0.0';
my $LOCAL_PORT=1234;
my $BUFFER = '0123456789ABCDEF' x (BUFSIZE/16);
my $srvSock;
$srvSock=IO::Socket::SSL->new(
LocalHost => $LOCAL_ADDR,
LocalPort => $LOCAL_PORT,
ReuseAddr => 1,
Listen => 1,
SSL_cert_file => 'cert.pem',
SSL_key_file => 'key.pem',
) or die "Failed to create listening SSL socket: $!";
print "SSL server listening on $LOCAL_ADDR:$LOCAL_PORT\n";
while() {
print "Waiting for client to connect...\n";
my $clientSock = $srvSock->accept()
or die "Failed to accept SSL client connection: $!, $SSL_ERROR\n";
print "Client connected, sending data.\n";
while() {
my $writeLength=syswrite($clientSock,$BUFFER)
or do {
print " Failed to write to client: $!, $SSL_ERROR\n";
last;
};
if($writeLength != BUFSIZE) {
print " Unexpected write length: $writeLength\n";
last;
}
}
}
####
use warnings;
use strict;
use IO::Socket::SSL;
use Time::HiRes qw'time';
use constant {
BUFSIZE => 16384,
INTERVAL => 1,
};
my $PEER_ADDR='192.168.1.10';
my $PEER_PORT=1234;
print "Connecting to SSL server ($PEER_ADDR:$PEER_PORT)\n";
my $clientSock = IO::Socket::SSL->new(
PeerHost => $PEER_ADDR,
PeerPort => $PEER_PORT,
Proto => 'tcp',
SSL_verify_mode => SSL_VERIFY_NONE,
) or die "Failed to connect to SSL server: $!, $SSL_ERROR";
print "Connected, switching to non-blocking mode.\n";
$clientSock->blocking(0);
my $sockVec='';
vec($sockVec,fileno($clientSock),1)=1;
my ($nbRead,$nbSslWantRead,$nbSslWantWrite,$transferred)=(0,0,0,0);
print "Downloading data from server...\n";
my $currentTime=time();
my ($intvlStart,$intvlEnd)=($currentTime,$currentTime+INTERVAL);
while() {
# There should be no pending data when BUFSIZE = max SSL frame size
die 'Unexpected pending data in SSL socket'
if($clientSock->pending());
$!=0;
select(my $readyVec=$sockVec,undef,undef,undef) > 0
or die "Error in select for read: $!";
my $readLength=sysread($clientSock,my $readData,BUFSIZE);
$nbRead++;
if(defined $readLength) {
die "Connection closed by peer"
unless($readLength);
die "Unexpected read length: $readLength"
unless($readLength == BUFSIZE);
}else{
die "Failed to read from SSL socket: $!"
unless($!{EWOULDBLOCK} || $!{EAGAIN});
if($SSL_ERROR == SSL_WANT_READ) {
$nbSslWantRead++;
next;
}
if($SSL_ERROR == SSL_WANT_WRITE) {
$nbSslWantWrite++;
select(undef,my $readyVec=$sockVec,undef,undef) > 0
or die "Error in select for write: $!";
next;
}
die 'Unexpected WOULDBLOCK/EAGAIN status when trying to read';
}
$transferred+=BUFSIZE;
$currentTime=time();
if($currentTime >= $intvlEnd) {
printReport();
initNewInterval();
}
}
sub printReport {
my $speed=formatSize($transferred/($currentTime-$intvlStart));
my $pctSslWantRead=sprintf('%.2f',$nbSslWantRead*100/$nbRead);
my $pctSslWantWrite=sprintf('%.2f',$nbSslWantWrite*100/$nbRead);
print "Transfer speed: $speed/s\n";
print " Read failure due to SSL_WANT_READ: $pctSslWantRead%\n";
print " Read failure due to SSL_WANT_WRITE: $pctSslWantWrite%\n";
}
sub formatSize {
my $size=shift;
my @UNITS=('',qw'K M G T');
my $unitIdx=0;
while($size >= 1000 && $unitIdx < $#UNITS) {
$size/=1000;
$unitIdx++;
}
$size=sprintf('%.2f',$size) if(index($size,'.') != -1);
return $size.' '.$UNITS[$unitIdx].'B';
}
sub initNewInterval {
($nbRead,$nbSslWantRead,$nbSslWantWrite,$transferred)=(0,0,0,0);
$intvlStart=$currentTime;
$intvlEnd+=INTERVAL while($intvlEnd < $intvlStart+INTERVAL/2);
}
####
$ perl sslclinb.pl
Connecting to SSL server (192.168.1.10:1234)
Connected, switching to non-blocking mode.
Downloading data from server...
Transfer speed: 117.55 MB/s
Read failure due to SSL_WANT_READ: 87.46%
Read failure due to SSL_WANT_WRITE: 0.00%
Transfer speed: 117.61 MB/s
Read failure due to SSL_WANT_READ: 90.84%
Read failure due to SSL_WANT_WRITE: 0.00%
Transfer speed: 117.61 MB/s
Read failure due to SSL_WANT_READ: 90.84%
Read failure due to SSL_WANT_WRITE: 0.00%
Transfer speed: 117.61 MB/s
Read failure due to SSL_WANT_READ: 90.88%
Read failure due to SSL_WANT_WRITE: 0.00%
Transfer speed: 117.61 MB/s
Read failure due to SSL_WANT_READ: 90.50%
Read failure due to SSL_WANT_WRITE: 0.00%
Transfer speed: 117.61 MB/s
Read failure due to SSL_WANT_READ: 82.52%
Read failure due to SSL_WANT_WRITE: 0.00%
Transfer speed: 117.61 MB/s
Read failure due to SSL_WANT_READ: 82.63%
Read failure due to SSL_WANT_WRITE: 0.00%
Transfer speed: 117.61 MB/s
Read failure due to SSL_WANT_READ: 82.58%
Read failure due to SSL_WANT_WRITE: 0.00%
Transfer speed: 117.61 MB/s
Read failure due to SSL_WANT_READ: 82.58%
Read failure due to SSL_WANT_WRITE: 0.00%
Transfer speed: 117.61 MB/s
Read failure due to SSL_WANT_READ: 82.57%
Read failure due to SSL_WANT_WRITE: 0.00%
^C