#!/usr/bin/perl

use warnings;
use strict;

use IO::Socket::SSL;

my $sock = IO::Socket::SSL->new(
    PeerAddr => "127.0.0.1:4433",
    SSL_ca_file => "/tmp/cert.pem",
    #SSL_mode_auto_no_retry => 1,
) // die;

my ($std_buf,  $std_off, $std_len)   = ("", 0, 0);
my ($sock_buf, $sock_off, $sock_len) = ("", 0, 0);

sub ssl_read() {
    if (defined (my $n = $sock->sysread($sock_buf, 4096, $sock_len))) {
        exit 0 unless $n > 0;
        $sock_len += $n;
    } elsif ($SSL_ERROR == SSL_WANT_READ) {
        print STDERR "SSL want read!\n";
    } else {
        die "sysread: $!";
    }
}

print STDERR "Entering loop...\n";
while (1) {
    if ((my $n = $sock->pending()) > 0) {
       print STDERR "$n bytes left in the current SSL frame\n";
       ssl_read();
       next;
    }

    my $rin = "";
    vec($rin, fileno(STDIN), 1) = 1;
    vec($rin, $sock->fileno(), 1) = 1;

    my $win = "";
    vec($win, fileno(STDOUT), 1)  = 1 if $sock_off < $sock_len;
    vec($win, $sock->fileno(), 1) = 1 if $std_off  < $std_len;

    select(my $rout = $rin, my $wout = $win, undef, undef);
    if (vec($rout, fileno(STDIN), 1) == 1) {
        my $n = sysread(STDIN, $std_buf, 4096, $std_len) // die "sysread: $!";
        exit 0 unless $n > 0;
        $std_len += $n;
    }
    if (vec($rout, $sock->fileno(), 1) == 1) {
       ssl_read();
    }
    if (vec($wout, fileno(STDOUT), 1) == 1) {
        my $n = syswrite(STDOUT, $sock_buf, $sock_len-$sock_off, $sock_off) // die "syswrite: $!";
        $sock_off += $n;
        ($sock_buf,  $sock_off, $sock_len) = ("", 0, 0) unless $sock_off < $sock_len;
    }
    if (vec($wout, $sock->fileno(), 1) == 1) {
        my $n = $sock->syswrite($std_buf, $std_len-$std_off, $std_off) // die "syswrite: $!";
        $std_off += $n;
        ($std_buf,  $std_off, $std_len) = ("", 0, 0) unless $std_off < $std_len;
    }
}
