Net::Proxy::Connector::dual - Y-shaped Net::Proxy connector


Net-Proxy documentation Contained in the Net-Proxy distribution.

Index


Code Index:

NAME

Top

Net::Proxy::Connector::dual - Y-shaped Net::Proxy connector

DESCRIPTION

Top

Net::Proxy::Connecter::dual is a Net::Proxy::Connector that can forward the connection to two distinct services, based on the client connection, before any data is exchanged.

CONNECTOR OPTIONS

Top

This connector can only work as an in connector.

The server_first and client_first options are required: they are hashrefs containing the options necessary to create two out Net::Proxy::Connector objects that will be used to connect to the requested service.

The Net::Proxy::Connector::dual object decides between the two services by waiting during a short timeout. If the client sends some data directly, then it is connected via the client_first connector. Otherwise, at the end of the timeout, it is connected via the server_first connector.

* host

The hostname on which the connector will listen for client connections. Default is localhost.

* port

The port on which the connector will listen for client connections.

* server_first

Typically an out connector to a SSH server or any service that sends a banner line.

* client_first

Typically an out connectrot to a web server or SSL server.

* timeout

The timeout in seconds (can be decimal) to make a decision. Default is 1 second.

AUTHOR

Top

Philippe 'BooK' Bruhat, <book@cpan.org>.

ACKNOWLEDGMENTS

Top

This module is based on a script named sslh, which I wrote with Frédéric Plé <sslh@wattoo.org> (who had the original insight about the fact that not all servers speak first on the wire).

Frédéric wrote a C program, while I wrote a Perl script (based on my experience with connect-tunnel).

Now that Net::Proxy is available, I've ported the Perl script to use it.

COPYRIGHT

Top

LICENSE

Top

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.


Net-Proxy documentation Contained in the Net-Proxy distribution.

package Net::Proxy::Connector::dual;
use strict;
use warnings;
use Carp;
use Scalar::Util qw( reftype );

use Net::Proxy::Connector;
our @ISA = qw( Net::Proxy::Connector );

sub init {
    my ($self) = @_;

    # check connectors
    for my $conn (qw( client_first server_first )) {
        croak "'$conn' connector required" if !exists $self->{$conn};

        croak "'$conn' connector must be a HASHREF"
            if ref $self->{$conn} ne 'HASH';

        croak "'type' key required for '$conn' connector"
            if !exists $self->{$conn}{type};

        croak "'hook' key is not a CODE reference for '$conn' connector"
            if $self->{$conn}{hook}
            && reftype( $self->{$conn}{hook} ) ne 'CODE';

        # load the class
        my $class = 'Net::Proxy::Connector::' . $self->{$conn}{type};
        eval "require $class";
        croak "Couldn't load $class for '$conn' connector: $@" if $@;

        # create and store the Connector object
        $self->{$conn} = $class->new( $self->{$conn} );
        $self->{$conn}->set_proxy($self->{_proxy_});
    }

    # other parameters
    croak q{Parameter 'port' is required} if !exists $self->{port};
    $self->{timeout} ||= 1;              # by default wait for one second
    $self->{host}    ||= 'localhost';    # by default listen on localhost

    return;
}

# IN
*listen = \&Net::Proxy::Connector::raw_listen;

sub accept_from {
    my ( $self, $listen ) = @_;
    my $sock = $self->raw_accept_from($listen);

    # find out who speaks first
    # if the client talks first, it's a client_first connection
    my $waiter = IO::Select->new($sock);
    my @waited = $waiter->can_read( $self->{timeout} );
    my $type   = @waited ? 'client_first' : 'server_first';

    # do the outgoing connection
    $self->{$type}->_out_connect_from($sock);

    return $sock;
}

# OUT

# READ
*read_from = \&Net::Proxy::Connector::raw_read_from;

# WRITE
*write_to = \&Net::Proxy::Connector::raw_write_to;

1;

__END__