Skip to content

Commit

Permalink
use IO::Socket::IP by default
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed Nov 4, 2014
1 parent a1ac74b commit 6759391
Show file tree
Hide file tree
Showing 14 changed files with 75 additions and 97 deletions.
7 changes: 6 additions & 1 deletion Makefile.PL
Expand Up @@ -7,6 +7,7 @@ use ExtUtils::MakeMaker;

# Pod::Simple 3.09 first shipped with Perl 5.11.2
# Time::Local 1.2 first shipped with Perl 5.13.9
# IO::Socket::IP 0.26 first shipped with Perl 5.19.8
WriteMakefile(
NAME => 'Mojolicious',
VERSION_FROM => 'lib/Mojolicious.pm',
Expand All @@ -24,7 +25,11 @@ WriteMakefile(
},
no_index => {directory => ['t']}
},
PREREQ_PM => {'Pod::Simple' => '3.09', 'Time::Local' => '1.2'},
PREREQ_PM => {
'IO::Socket::IP' => '0.26',
'Pod::Simple' => '3.09',
'Time::Local' => '1.2'
},
EXE_FILES => ['script/hypnotoad', 'script/mojo', 'script/morbo'],
test => {TESTS => 't/*.t t/*/*.t'}
);
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -18,7 +18,7 @@
testing framework, static file server, first class Unicode support and
much more for you to discover.
* Very clean, portable and object-oriented pure-Perl API with no hidden
magic and no requirements besides Perl 5.18.0 (versions as old as 5.10.1
magic and no requirements besides Perl 5.20.0 (versions as old as 5.10.1
can be used too, but may require additional CPAN modules to be installed)
* Full stack HTTP and WebSocket client/server implementation with IPv6, TLS,
SNI, IDNA, HTTP/SOCKS5 proxy, Comet (long polling), keep-alive, connection
Expand Down
16 changes: 6 additions & 10 deletions lib/Mojo/IOLoop.pm
Expand Up @@ -314,22 +314,18 @@ scalable C<select>.
LIBEV_FLAGS=4 # epoll (Linux)
LIBEV_FLAGS=8 # kqueue (*BSD, OS X)
Connections are established non-blocking, but name resolution needs to be
performed blocking, so you should reduce concurrency if resolver timeouts are
a possibility.
The event loop will be resilient to time jumps if a monotonic clock is
available through L<Time::HiRes>. A TLS certificate and key are also built
right in, to make writing test servers as easy as possible. Also note that for
convenience the C<PIPE> signal will be set to C<IGNORE> when L<Mojo::IOLoop>
is loaded.
For better scalability (epoll, kqueue) and to provide IPv6, SOCKS5 as well as
TLS support, the optional modules L<EV> (4.0+), L<IO::Socket::IP> (0.20+),
L<IO::Socket::Socks> (0.64+) and L<IO::Socket::SSL> (1.84+) will be used
automatically if they are installed. Individual features can also be disabled
with the C<MOJO_NO_IPV6>, C<MOJO_NO_SOCKS> and C<MOJO_NO_TLS> environment
variables.
For better scalability (epoll, kqueue) and to provide non-blocking name
resolution, SOCKS5 as well as TLS support, the optional modules L<EV> (4.0+),
L<Net::DNS::Native> (0.10+), L<IO::Socket::Socks> (0.64+) and
L<IO::Socket::SSL> (1.84+) will be used automatically if they are installed.
Individual features can also be disabled with the C<MOJO_NO_DNS>,
C<MOJO_NO_SOCKS> and C<MOJO_NO_TLS> environment variables.
See L<Mojolicious::Guides::Cookbook/"REAL-TIME WEB"> for more.
Expand Down
60 changes: 23 additions & 37 deletions lib/Mojo/IOLoop/Client.pm
Expand Up @@ -2,22 +2,17 @@ package Mojo::IOLoop::Client;
use Mojo::Base 'Mojo::EventEmitter';

use Errno 'EINPROGRESS';
use IO::Socket::INET;
use IO::Socket::IP;
use Mojo::IOLoop;
use Scalar::Util 'weaken';
use Socket qw(IPPROTO_TCP SO_ERROR TCP_NODELAY);

# Non-blocking resolver support requires Net::DNS::Native
# Non-blocking name resolution requires Net::DNS::Native
use constant DNS => $ENV{MOJO_NO_DNS}
? 0
: eval 'use Net::DNS::Native 0.10 (); 1';
my $DNS = DNS ? Net::DNS::Native->new : undef;

# IPv6 support requires IO::Socket::IP
use constant IPV6 => $ENV{MOJO_NO_IPV6}
? 0
: eval 'use IO::Socket::IP 0.20 (); 1';

# TLS support requires IO::Socket::SSL
use constant TLS => $ENV{MOJO_NO_TLS}
? 0
Expand Down Expand Up @@ -46,38 +41,29 @@ sub connect {
$self->{timer} = $reactor->timer($args->{timeout} || 10,
sub { $self->emit(error => 'Connect timeout') });

# Non-blocking resolver
# Blocking name resolution
my $address = $args->{socks_address} || ($args->{address} ||= 'localhost');
if (DNS && $address ne 'localhost') {
my $handle = $DNS->getaddrinfo($address, undef, {});
$reactor->io(
$handle => sub {
shift->remove($handle);

my ($err, @res) = $DNS->get_result($handle);
return $self->emit(error => "Can't resolve: $err") if $err;

my $r = $res[0];
my $address
= $r->{family} == AF_INET
? Socket::inet_ntoa((Socket::unpack_sockaddr_in($r->{addr}))[1])
: Socket::inet_ntop(Socket::AF_INET6,
(Socket::unpack_sockaddr_in6($r->{addr}))[1]);
$args->{$args->{socks_address} ? 'socks_address' : 'address'}
= $address;

$self->_connect($args);
}
)->watch($handle, 1, 0);
}

$reactor->next_tick(sub { $self && $self->_connect($args) });
return $reactor->next_tick(sub { $self && $self->_connect($args) })
unless DNS && $address ne 'localhost';

# Non-blocking name resolution
my $handle = $self->{dns} = $DNS->getaddrinfo($address, undef, {});
$reactor->io(
$handle => sub {
shift->remove($handle);

my ($err, @res) = $DNS->get_result($handle);
return $self->emit(error => "Can't resolve: $err") if $err;
$args->{addr_info} = \@res;
$self->_connect($args);
}
)->watch($handle, 1, 0);
}

sub _cleanup {
my $self = shift;
return $self unless my $reactor = $self->reactor;
$self->{$_} && $reactor->remove(delete $self->{$_}) for qw(timer handle);
$self->{$_} && $reactor->remove(delete $self->{$_}) for qw(dns timer handle);
return $self;
}

Expand All @@ -89,15 +75,15 @@ sub _connect {
my $port = $args->{socks_port} || $args->{port} || ($args->{tls} ? 443 : 80);
unless ($handle = $self->{handle} = $args->{handle}) {
my %options = (
Blocking => 0,
PeerAddr => $address eq 'localhost' ? '127.0.0.1' : $address,
PeerPort => $port
);
%options = (PeerAddrInfo => $args->{addr_info}) if $args->{addr_info};
$options{Blocking} = 0;
$options{LocalAddr} = $args->{local_address} if $args->{local_address};
$options{PeerAddr} =~ s/[\[\]]//g if $options{PeerAddr};
my $class = IPV6 ? 'IO::Socket::IP' : 'IO::Socket::INET';
return $self->emit(error => "Can't connect: $@")
unless $self->{handle} = $handle = $class->new(%options);
unless $self->{handle} = $handle = IO::Socket::IP->new(%options);
}
$handle->blocking(0);

Expand Down Expand Up @@ -278,7 +264,7 @@ implements the following new ones.
$client->connect(address => '127.0.0.1', port => 3000);
Open a socket connection to a remote host. Note that TLS support depends on
L<IO::Socket::SSL> (1.84+) and IPv6 support on L<IO::Socket::IP> (0.20+).
L<IO::Socket::SSL> (1.84+).
These options are currently available:
Expand Down
17 changes: 6 additions & 11 deletions lib/Mojo/IOLoop/Server.pm
Expand Up @@ -4,16 +4,11 @@ use Mojo::Base 'Mojo::EventEmitter';
use Carp 'croak';
use File::Basename 'dirname';
use File::Spec::Functions 'catfile';
use IO::Socket::INET;
use IO::Socket::IP;
use Mojo::IOLoop;
use Scalar::Util 'weaken';
use Socket qw(IPPROTO_TCP TCP_NODELAY);

# IPv6 support requires IO::Socket::IP
use constant IPV6 => $ENV{MOJO_NO_IPV6}
? 0
: eval 'use IO::Socket::IP 0.20 (); 1';

# TLS support requires IO::Socket::SSL
use constant TLS => $ENV{MOJO_NO_TLS}
? 0
Expand All @@ -38,7 +33,7 @@ sub DESTROY {
}

sub generate_port {
IO::Socket::INET->new(Listen => 5, LocalAddr => '127.0.0.1')->sockport;
IO::Socket::IP->new(Listen => 5, LocalAddr => '127.0.0.1')->sockport;
}

sub handle { shift->{handle} }
Expand All @@ -59,9 +54,8 @@ sub listen {

# Reuse file descriptor
my $handle;
my $class = IPV6 ? 'IO::Socket::IP' : 'IO::Socket::INET';
if (defined $fd) {
$handle = $class->new_from_fd($fd, 'r')
$handle = IO::Socket::IP->new_from_fd($fd, 'r')
or croak "Can't open file descriptor $fd: $!";
}

Expand All @@ -76,7 +70,8 @@ sub listen {
);
$options{LocalPort} = $port if $port;
$options{LocalAddr} =~ s/[\[\]]//g;
$handle = $class->new(%options) or croak "Can't create listen socket: $@";
$handle = IO::Socket::IP->new(%options)
or croak "Can't create listen socket: $@";
$fd = fileno $handle;
my $reuse = $self->{reuse} = join ':', $address, $handle->sockport, $fd;
$ENV{MOJO_REUSE} .= length $ENV{MOJO_REUSE} ? ",$reuse" : "$reuse";
Expand Down Expand Up @@ -238,7 +233,7 @@ Get handle for server.
$server->listen(port => 3000);
Create a new listen socket. Note that TLS support depends on
L<IO::Socket::SSL> (1.84+) and IPv6 support on L<IO::Socket::IP> (0.20+).
L<IO::Socket::SSL> (1.84+).
These options are currently available:
Expand Down
12 changes: 6 additions & 6 deletions lib/Mojo/Server/Daemon.pm
Expand Up @@ -264,12 +264,12 @@ L<Mojo::Server::Daemon> is a full featured, highly portable non-blocking I/O
HTTP and WebSocket server, with IPv6, TLS, Comet (long polling), keep-alive
and multiple event loop support.
For better scalability (epoll, kqueue) and to provide IPv6, SOCKS5 as well as
TLS support, the optional modules L<EV> (4.0+), L<IO::Socket::IP> (0.20+),
L<IO::Socket::Socks> (0.64+) and L<IO::Socket::SSL> (1.84+) will be used
automatically if they are installed. Individual features can also be disabled
with the C<MOJO_NO_IPV6>, C<MOJO_NO_SOCKS> and C<MOJO_NO_TLS> environment
variables.
For better scalability (epoll, kqueue) and to provide non-blocking name
resolution, SOCKS5 as well as TLS support, the optional modules L<EV> (4.0+),
L<Net::DNS::Native> (0.10+), L<IO::Socket::Socks> (0.64+) and
L<IO::Socket::SSL> (1.84+) will be used automatically if they are installed.
Individual features can also be disabled with the C<MOJO_NO_DNS>,
C<MOJO_NO_SOCKS> and C<MOJO_NO_TLS> environment variables.
See L<Mojolicious::Guides::Cookbook/"DEPLOYMENT"> for more.
Expand Down
12 changes: 6 additions & 6 deletions lib/Mojo/Server/Hypnotoad.pm
Expand Up @@ -171,12 +171,12 @@ You can run the same command again for automatic hot deployment.
This second invocation will load the application again, detect the process id
file with it, and send a L</"USR2"> signal to the already running server.
For better scalability (epoll, kqueue) and to provide IPv6, SOCKS5 as well as
TLS support, the optional modules L<EV> (4.0+), L<IO::Socket::IP> (0.20+),
L<IO::Socket::Socks> (0.64+) and L<IO::Socket::SSL> (1.84+) will be used
automatically if they are installed. Individual features can also be disabled
with the C<MOJO_NO_IPV6>, C<MOJO_NO_SOCKS> and C<MOJO_NO_TLS> environment
variables.
For better scalability (epoll, kqueue) and to provide non-blocking name
resolution, SOCKS5 as well as TLS support, the optional modules L<EV> (4.0+),
L<Net::DNS::Native> (0.10+), L<IO::Socket::Socks> (0.64+) and
L<IO::Socket::SSL> (1.84+) will be used automatically if they are installed.
Individual features can also be disabled with the C<MOJO_NO_DNS>,
C<MOJO_NO_SOCKS> and C<MOJO_NO_TLS> environment variables.
See L<Mojolicious::Guides::Cookbook/"DEPLOYMENT"> for more.
Expand Down
12 changes: 6 additions & 6 deletions lib/Mojo/Server/Morbo.pm
Expand Up @@ -130,12 +130,12 @@ To start applications with it you can use the L<morbo> script.
$ morbo ./myapp.pl
Server available at http://127.0.0.1:3000.
For better scalability (epoll, kqueue) and to provide IPv6, SOCKS5 as well as
TLS support, the optional modules L<EV> (4.0+), L<IO::Socket::IP> (0.20+),
L<IO::Socket::Socks> (0.64+) and L<IO::Socket::SSL> (1.84+) will be used
automatically if they are installed. Individual features can also be disabled
with the C<MOJO_NO_IPV6>, C<MOJO_NO_SOCKS> and C<MOJO_NO_TLS> environment
variables.
For better scalability (epoll, kqueue) and to provide non-blocking name
resolution, SOCKS5 as well as TLS support, the optional modules L<EV> (4.0+),
L<Net::DNS::Native> (0.10+), L<IO::Socket::Socks> (0.64+) and
L<IO::Socket::SSL> (1.84+) will be used automatically if they are installed.
Individual features can also be disabled with the C<MOJO_NO_DNS>,
C<MOJO_NO_SOCKS> and C<MOJO_NO_TLS> environment variables.
See L<Mojolicious::Guides::Cookbook/"DEPLOYMENT"> for more.
Expand Down
12 changes: 6 additions & 6 deletions lib/Mojo/Server/Prefork.pm
Expand Up @@ -261,12 +261,12 @@ keep-alive and multiple event loop support. Note that the server uses signals
for process management, so you should avoid modifying signal handlers in your
applications.
For better scalability (epoll, kqueue) and to provide IPv6, SOCKS5 as well as
TLS support, the optional modules L<EV> (4.0+), L<IO::Socket::IP> (0.20+),
L<IO::Socket::Socks> (0.64+) and L<IO::Socket::SSL> (1.84+) will be used
automatically if they are installed. Individual features can also be disabled
with the C<MOJO_NO_IPV6>, C<MOJO_NO_SOCKS> and C<MOJO_NO_TLS> environment
variables.
For better scalability (epoll, kqueue) and to provide non-blocking name
resolution, SOCKS5 as well as TLS support, the optional modules L<EV> (4.0+),
L<Net::DNS::Native> (0.10+), L<IO::Socket::Socks> (0.64+) and
L<IO::Socket::SSL> (1.84+) will be used automatically if they are installed.
Individual features can also be disabled with the C<MOJO_NO_DNS>,
C<MOJO_NO_SOCKS> and C<MOJO_NO_TLS> environment variables.
See L<Mojolicious::Guides::Cookbook/"DEPLOYMENT"> for more.
Expand Down
12 changes: 6 additions & 6 deletions lib/Mojo/UserAgent.pm
Expand Up @@ -440,12 +440,12 @@ All connections will be reset automatically if a new process has been forked,
this allows multiple processes to share the same L<Mojo::UserAgent> object
safely.
For better scalability (epoll, kqueue) and to provide IPv6, SOCKS5 as well as
TLS support, the optional modules L<EV> (4.0+), L<IO::Socket::IP> (0.20+),
L<IO::Socket::Socks> (0.64+) and L<IO::Socket::SSL> (1.84+) will be used
automatically if they are installed. Individual features can also be disabled
with the C<MOJO_NO_IPV6>, C<MOJO_NO_SOCKS> and C<MOJO_NO_TLS> environment
variables.
For better scalability (epoll, kqueue) and to provide non-blocking name
resolution, SOCKS5 as well as TLS support, the optional modules L<EV> (4.0+),
L<Net::DNS::Native> (0.10+), L<IO::Socket::Socks> (0.64+) and
L<IO::Socket::SSL> (1.84+) will be used automatically if they are installed.
Individual features can also be disabled with the C<MOJO_NO_DNS>,
C<MOJO_NO_SOCKS> and C<MOJO_NO_TLS> environment variables.
See L<Mojolicious::Guides::Cookbook/"USER AGENT"> for more.
Expand Down
4 changes: 2 additions & 2 deletions lib/Mojolicious/Command/version.pm
Expand Up @@ -13,7 +13,7 @@ sub run {

my $ev = eval 'use Mojo::Reactor::EV; 1' ? $EV::VERSION : 'not installed';
my $class = 'Mojo::IOLoop::Client';
my $ipv6 = $class->IPV6 ? $IO::Socket::IP::VERSION : 'not installed';
my $dns = $class->DNS ? $Net::DNS::Native::VERSION : 'not installed';
my $socks = $class->SOCKS ? $IO::Socket::Socks::VERSION : 'not installed';
my $tls = $class->TLS ? $IO::Socket::SSL::VERSION : 'not installed';

Expand All @@ -24,7 +24,7 @@ CORE
OPTIONAL
EV 4.0+ ($ev)
IO::Socket::IP 0.20+ ($ipv6)
Net::DNS::Native 0.10+ ($dns)
IO::Socket::Socks 0.64+ ($socks)
IO::Socket::SSL 1.84+ ($tls)
Expand Down
2 changes: 1 addition & 1 deletion lib/Mojolicious/Guides/FAQ.pod
Expand Up @@ -34,7 +34,7 @@ without compromises. While there are no rules in
L<Mojolicious::Guides::Contributing> that forbid dependencies, we do currently
discourage adding non-optional ones in favor of a faster and more painless
installation process. And we do in fact already use several optional CPAN
modules such as L<EV>, L<IO::Socket::IP>, L<IO::Socket::Socks>,
modules such as L<EV>, L<Net::DNS::Native>, L<IO::Socket::Socks>,
L<IO::Socket::SSL> and L<Plack> to provide advanced functionality if they are
installed.

Expand Down
2 changes: 0 additions & 2 deletions t/mojo/ioloop_ipv6.t
Expand Up @@ -7,8 +7,6 @@ use Mojo::IOLoop::Server;

plan skip_all => 'set TEST_IPV6 to enable this test (developer only!)'
unless $ENV{TEST_IPV6};
plan skip_all => 'IO::Socket::IP 0.20 required for this test!'
unless Mojo::IOLoop::Server::IPV6;

use Mojo::IOLoop;

Expand Down
2 changes: 0 additions & 2 deletions t/mojo/user_agent_online.t
Expand Up @@ -10,8 +10,6 @@ use Mojo::IOLoop::Server;

plan skip_all => 'set TEST_ONLINE to enable this test (developer only!)'
unless $ENV{TEST_ONLINE};
plan skip_all => 'IO::Socket::IP 0.20 required for this test!'
unless Mojo::IOLoop::Server::IPV6;
plan skip_all => 'IO::Socket::SSL 1.84 required for this test!'
unless Mojo::IOLoop::Server::TLS;

Expand Down

0 comments on commit 6759391

Please sign in to comment.