# Use case: client connect to echo server. # Use case: client connect to echo server using proxy. use warnings; use strict; use lib 't'; use share; use constant ACCEPTED => 123; @CheckPoint = ( # first test: client connect to server without proxy ['listener_server', ACCEPTED ], 'server: new client', ['server', IN ], 'server: IN', ['server', 'test' ], ' received "test"', ['server', SENT ], 'server: SENT', ['client', EOF ], 'client: EOF', ['client', 'passed' ], ' received "passed"', # second test: client connect to server using proxy ['listener_proxy', ACCEPTED ], 'proxy: new client', { win32_somefreebsd => [ ['listener_server', ACCEPTED ], 'server: new client', ['proxy2server', CONNECTED ], 'proxy2server: CONNECTED', ], other => [ ['proxy2server', CONNECTED ], 'proxy2server: CONNECTED', ['listener_server', ACCEPTED ], 'server: new client', ], }, ['proxy2client', IN ], 'proxy2client: IN', ['server', IN ], 'server: IN', ['server', 'test' ], ' received "test"', ['server', SENT ], 'server: SENT', ['proxy2server', IN ], 'proxy2server: IN', ['proxy2client', SENT ], 'proxy2client: SENT', ['proxy2server', EOF ], 'proxy2server: EOF', ['client2', EOF ], 'client2: EOF', ['client2', 'passed' ], ' received "passed"', ); plan tests => 2 # {is_eof} tests in client() and client2() + checkpoint_count(); my $srv_sock = tcp_server('127.0.0.1', 0); my $srv_w = EV::io($srv_sock, EV::READ, \&listener_server); my $prx_sock = tcp_server('127.0.0.1', 0); my $prx_w = EV::io($prx_sock, EV::READ, \&listener_proxy); sub new_client { my ($port, $cb) = @_; IO::Stream->new({ host => '127.0.0.1', port => $port, cb => $cb, wait_for => EOF, out_buf => 'test', in_buf_limit=> 1024, }); } new_client(sockport($srv_sock), \&client); EV::loop; sub listener_server { if (accept my $sock, $srv_sock) { checkpoint(ACCEPTED); IO::Stream->new({ fh => $sock, cb => \&server, wait_for => IN, }); } elsif ($! != EAGAIN) { die "accept: $!\n"; } } sub server { my ($io, $e, $err) = @_; die "server error: $err\n" if $err; checkpoint($e); if ($e & IN) { checkpoint($io->{in_buf}); $io->{wait_for} = SENT; $io->write('passed'); } if ($e & SENT) { $io->close(); } } sub listener_proxy { if (accept my $sock, $prx_sock) { checkpoint(ACCEPTED); IO::Stream->new({ host => '127.0.0.1', port => sockport($srv_sock), cb => \&proxy2server, wait_for => CONNECTED|IN|EOF, Client => undef, ClientSock => $sock, }); } elsif ($! != EAGAIN) { die "accept: $!\n"; } } sub proxy2server { my ($io, $e, $err) = @_; die "proxy2server error: $err\n" if $err; checkpoint($e); if ($e & CONNECTED) { $io->{Client} = IO::Stream->new({ fh => $io->{ClientSock}, cb => \&proxy2client, wait_for => IN|EOF|SENT, Server => $io, }); weaken($io->{Client}->{Server}); weaken($io->{Client}); } if ($e & SENT) { shutdown $io->{fh}, 1; } if ($e & IN) { $io->{Client}->write($io->{in_buf}); $io->{in_buf} = q{}; } if ($e & EOF) { $io->close(); } } sub proxy2client { my ($io, $e, $err) = @_; die "proxy2client error: $err\n" if $err; checkpoint($e); if ($e & IN) { $io->{Server}->write($io->{in_buf}); $io->{in_buf} = q{}; } if ($e & EOF) { if (length($io->{Server}->{out_buf})) { $io->{Server}->{wait_for} = IN|SENT; } else { shutdown $io->{Server}->{fh}, 1; } } if ($e & SENT) { $io->close(); } } sub client { my ($io, $e, $err) = @_; die "client error: $err\n" if $err; checkpoint($e); checkpoint($io->{in_buf}); ok($io->{is_eof}, ' {is_eof} set'); $io->close(); new_client(sockport($prx_sock), \&client2); } sub client2 { my ($io, $e, $err) = @_; die "client2 error: $err\n" if $err; checkpoint($e); checkpoint($io->{in_buf}); ok($io->{is_eof}, ' {is_eof} set'); $io->close(); EV::unloop; }