#!/usr/bin/perl
use strict; use warnings;
# to use experimental nonblocking, uncomment this line
#sub POE::Component::SSLify::NONBLOCKING { 1 }
use POE;
use Socket qw( inet_ntoa unpack_sockaddr_in );
use POE::Component::SSLify qw( Client_SSLify Server_SSLify SSLify_Options SSLify_GetCipher SSLify_GetSocket );
use POE::Wheel::ReadWrite;
use POE::Wheel::SocketFactory;
use POE::Driver::SysRW;
use POE::Filter::Line;
use POE::Wheel::ReadLine;
# create the server
POE::Session->create(
'inline_states' => {
'_start' => sub {
# Okay, set the SSL options
SSLify_Options( 'server.key', 'server.crt' );
# Set the alias
$_[KERNEL]->alias_set( 'server' );
# Create the socketfactory wheel to listen for requests
$_[HEAP]->{'SOCKETFACTORY'} = POE::Wheel::SocketFactory->new(
'BindPort' => 5432,
'BindAddress' => 'localhost',
'Reuse' => 'yes',
'SuccessEvent' => 'Got_Connection',
'FailureEvent' => 'ListenerError',
);
return 1;
},
'Got_Connection' => sub {
# ARG0 = Socket, ARG1 = Remote Address, ARG2 = Remote Port
my $socket = $_[ ARG0 ];
# testing stuff
warn "got connection from: " . inet_ntoa( ( unpack_sockaddr_in( getpeername( $socket ) ) )[1] ) . " - commencing Server_SSLify()";
# SSLify it!
$socket = Server_SSLify( $socket );
# testing stuff
warn "SSLified: " . inet_ntoa( ( unpack_sockaddr_in( getpeername( SSLify_GetSocket( $socket ) ) ) )[1] ) . " cipher type: " . SSLify_GetCipher( $socket );
# Hand it off to ReadWrite
my $wheel = POE::Wheel::ReadWrite->new(
'Handle' => $socket,
'Driver' => POE::Driver::SysRW->new(),
'Filter' => POE::Filter::Line->new(),
'InputEvent' => 'Got_Input',
'ErrorEvent' => 'Got_Error',
);
# Store it...
$_[HEAP]->{'WHEELS'}->{ $wheel->ID } = $wheel;
return;
},
'ListenerError' => sub {
# ARG0 = operation, ARG1 = error number, ARG2 = error string, ARG3 = wheel ID
my ( $operation, $errnum, $errstr, $wheel_id ) = @_[ ARG0 .. ARG3 ];
warn "SocketFactory Wheel $wheel_id generated $operation error $errnum: $errstr\n";
return;
},
'Got_Input' => sub {
# ARG0: The Line, ARG1: Wheel ID
# Send back to the client the line!
$_[HEAP]->{'WHEELS'}->{ $_[ARG1] }->put( $_[ARG0] );
return;
},
'Got_Error' => sub {
# ARG0 = operation, ARG1 = error number, ARG2 = error string, ARG3 = wheel ID
my ( $operation, $errnum, $errstr, $id ) = @_[ ARG0 .. ARG3 ];
warn "Wheel $id generated $operation error $errnum: $errstr\n";
# Done with a wheel
delete $_[HEAP]->{'WHEELS'}->{ $_[ARG0] };
return;
},
},
);
# create the client
POE::Session->create(
'inline_states' => {
'_start' => sub {
# Set the alias
$_[KERNEL]->alias_set( 'client' );
# Setup our ReadLine stuff
$_[HEAP]->{'RL'} = POE::Wheel::ReadLine->new(
'InputEvent' => 'Got_ReadLine',
);
# Connect to the server!
$_[KERNEL]->yield( 'do_connect' );
return;
},
'do_connect' => sub {
# Create the socketfactory wheel to listen for requests
$_[HEAP]->{'SOCKETFACTORY'} = POE::Wheel::SocketFactory->new(
'RemotePort' => 5432,
'RemoteAddress' => 'localhost',
'Reuse' => 'yes',
'SuccessEvent' => 'Got_Connection',
'FailureEvent' => 'ConnectError',
);
return;
},
'Got_ReadLine' => sub {
if ( defined $_[ARG0] ) {
if ( exists $_[HEAP]->{'WHEEL'} ) {
$_[HEAP]->{'WHEEL'}->put( $_[ARG0] );
}
} else {
if ( $_[ARG1] eq 'interrupt' ) {
die 'stopped';
}
}
return;
},
'Got_Connection' => sub {
# ARG0 = Socket, ARG1 = Remote Address, ARG2 = Remote Port
my $socket = $_[ ARG0 ];
warn "Connected to server, commencing Client_SSLify()";
# SSLify it!
$socket = Client_SSLify( $socket );
warn "SSLified the connection to the server";
# Hand it off to ReadWrite
my $wheel = POE::Wheel::ReadWrite->new(
'Handle' => $socket,
'Driver' => POE::Driver::SysRW->new(),
'Filter' => POE::Filter::Line->new(),
'InputEvent' => 'Got_Input',
'ErrorEvent' => 'Got_Error',
);
# Store it...
$_[HEAP]->{'WHEEL'} = $wheel;
$_[HEAP]->{'RL'}->put( 'Connected to SSL server' );
$_[HEAP]->{'RL'}->get( 'Input: ' );
return;
},
'ConnectError' => sub {
# ARG0 = operation, ARG1 = error number, ARG2 = error string, ARG3 = wheel ID
my ( $operation, $errnum, $errstr, $wheel_id ) = @_[ ARG0 .. ARG3 ];
warn "SocketFactory Wheel $wheel_id generated $operation error $errnum: $errstr\n";
delete $_[HEAP]->{'SOCKETFACTORY'};
$_[HEAP]->{'RL'}->put( 'Unable to connect to SSL server...' );
$_[KERNEL]->delay_set( 'do_connect', 5 );
return;
},
'Got_Input' => sub {
# ARG0: The Line, ARG1: Wheel ID
# Send back to the client the line!
$_[HEAP]->{'RL'}->put( 'Got Reply: ' . $_[ARG0] );
$_[HEAP]->{'RL'}->get( 'Input: ' );
return;
},
'Got_Error' => sub {
# ARG0 = operation, ARG1 = error number, ARG2 = error string, ARG3 = wheel ID
my ( $operation, $errnum, $errstr, $id ) = @_[ ARG0 .. ARG3 ];
warn "Wheel $id generated $operation error $errnum: $errstr\n";
delete $_[HEAP]->{'WHEEL'};
$_[HEAP]->{'RL'}->put( 'Disconnected from SSL server...' );
$_[KERNEL]->delay_set( 'do_connect', 5 );
return;
},
},
);
# Start POE!
POE::Kernel->run();
exit 0;