400 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			400 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 3443626f53d8283935e41f39ee6cf93096019cd1 Mon Sep 17 00:00:00 2001
 | |
| From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
 | |
| Date: Mon, 16 Jan 2017 16:13:08 +0100
 | |
| Subject: [PATCH] Add IPv6 support
 | |
| MIME-Version: 1.0
 | |
| Content-Type: text/plain; charset=UTF-8
 | |
| Content-Transfer-Encoding: 8bit
 | |
| 
 | |
| This patch ports the code from IO::Socket::INET to IO::Socket::IP in
 | |
| order to support IPv6.
 | |
| 
 | |
| CPAN RT #91699, #71395.
 | |
| 
 | |
| Signed-off-by: Petr Písař <ppisar@redhat.com>
 | |
| ---
 | |
|  Build.PL               |  7 ++++---
 | |
|  META.json              |  5 +++--
 | |
|  META.yml               |  3 ++-
 | |
|  Makefile.PL            |  8 ++++----
 | |
|  lib/HTTP/Daemon.pm     | 43 +++++++++++++++++++++++++++---------------
 | |
|  t/00-report-prereqs.dd |  5 +++--
 | |
|  t/chunked.t            | 34 ++++++++++++++++++++++-----------
 | |
|  t/local/http.t         |  2 +-
 | |
|  t/robot/ua-get.t       |  2 +-
 | |
|  t/robot/ua.t           |  2 +-
 | |
|  10 files changed, 70 insertions(+), 41 deletions(-)
 | |
| 
 | |
| diff --git a/Build.PL b/Build.PL
 | |
| index b44b1c5..9a040b1 100644
 | |
| --- a/Build.PL
 | |
| +++ b/Build.PL
 | |
| @@ -97,8 +97,9 @@ EOW
 | |
|          "HTTP::Request" => 6,
 | |
|          "HTTP::Response" => 6,
 | |
|          "HTTP::Status" => 6,
 | |
| -        "IO::Socket" => 0,
 | |
| +        "IO::Socket::IP" => 0,
 | |
|          "LWP::MediaTypes" => 6,
 | |
| +        "Socket" => 0,
 | |
|          "Sys::Hostname" => 0,
 | |
|          "perl" => "5.006",
 | |
|          "strict" => 0,
 | |
| @@ -106,7 +107,7 @@ EOW
 | |
|        },
 | |
|        "test_requires" => {
 | |
|          "File::Spec" => 0,
 | |
| -        "IO::Socket::INET" => 0,
 | |
| +        "IO::Socket::IP" => 0,
 | |
|          "Module::Metadata" => 0,
 | |
|          "Socket" => 0,
 | |
|          "Test" => 0,
 | |
| @@ -120,7 +121,7 @@ EOW
 | |
|  
 | |
|      my %fallback_build_requires = (
 | |
|        "File::Spec" => 0,
 | |
| -      "IO::Socket::INET" => 0,
 | |
| +      "IO::Socket::IP" => 0,
 | |
|        "Module::Metadata" => 0,
 | |
|        "Socket" => 0,
 | |
|        "Test" => 0,
 | |
| diff --git a/META.json b/META.json
 | |
| index 67d7de5..badff90 100644
 | |
| --- a/META.json
 | |
| +++ b/META.json
 | |
| @@ -61,8 +61,9 @@
 | |
|              "HTTP::Request" : "6",
 | |
|              "HTTP::Response" : "6",
 | |
|              "HTTP::Status" : "6",
 | |
| -            "IO::Socket" : "0",
 | |
| +            "IO::Socket::IP" : "0",
 | |
|              "LWP::MediaTypes" : "6",
 | |
| +            "Socket" : "0",
 | |
|              "Sys::Hostname" : "0",
 | |
|              "perl" : "5.006",
 | |
|              "strict" : "0",
 | |
| @@ -75,7 +76,7 @@
 | |
|           },
 | |
|           "requires" : {
 | |
|              "File::Spec" : "0",
 | |
| -            "IO::Socket::INET" : "0",
 | |
| +            "IO::Socket::IP" : "0",
 | |
|              "Module::Metadata" : "0",
 | |
|              "Socket" : "0",
 | |
|              "Test" : "0",
 | |
| diff --git a/META.yml b/META.yml
 | |
| index 4f76ff2..2d8a4e2 100644
 | |
| --- a/META.yml
 | |
| +++ b/META.yml
 | |
| @@ -4,7 +4,7 @@ author:
 | |
|    - 'Gisle Aas <gisle@activestate.com>'
 | |
|  build_requires:
 | |
|    File::Spec: '0'
 | |
| -  IO::Socket::INET: '0'
 | |
| +  IO::Socket::IP: '0'
 | |
|    Module::Metadata: '0'
 | |
|    Socket: '0'
 | |
|    Test: '0'
 | |
| @@ -38,6 +38,7 @@ requires:
 | |
|    HTTP::Response: '6'
 | |
|    HTTP::Status: '6'
 | |
|    IO::Socket: '0'
 | |
| +  IO::Socket::IP: '0'
 | |
|    LWP::MediaTypes: '6'
 | |
|    Sys::Hostname: '0'
 | |
|    perl: '5.006'
 | |
| diff --git a/Makefile.PL b/Makefile.PL
 | |
| index aa76f2b..5915c46 100644
 | |
| --- a/Makefile.PL
 | |
| +++ b/Makefile.PL
 | |
| @@ -88,15 +88,16 @@ my %WriteMakefileArgs = (
 | |
|      "HTTP::Request" => 6,
 | |
|      "HTTP::Response" => 6,
 | |
|      "HTTP::Status" => 6,
 | |
| -    "IO::Socket" => 0,
 | |
| +    "IO::Socket::IP" => 0,
 | |
|      "LWP::MediaTypes" => 6,
 | |
| +    "Socket" => 0,
 | |
|      "Sys::Hostname" => 0,
 | |
|      "strict" => 0,
 | |
|      "warnings" => 0
 | |
|    },
 | |
|    "TEST_REQUIRES" => {
 | |
|      "File::Spec" => 0,
 | |
| -    "IO::Socket::INET" => 0,
 | |
| +    "IO::Socket::IP" => 0,
 | |
|      "Module::Metadata" => 0,
 | |
|      "Socket" => 0,
 | |
|      "Test" => 0,
 | |
| @@ -117,8 +118,7 @@ my %FallbackPrereqs = (
 | |
|    "HTTP::Request" => 6,
 | |
|    "HTTP::Response" => 6,
 | |
|    "HTTP::Status" => 6,
 | |
| -  "IO::Socket" => 0,
 | |
| -  "IO::Socket::INET" => 0,
 | |
| +  "IO::Socket::IP" => 0,
 | |
|    "LWP::MediaTypes" => 6,
 | |
|    "Module::Metadata" => 0,
 | |
|    "Socket" => 0,
 | |
| diff --git a/lib/HTTP/Daemon.pm b/lib/HTTP/Daemon.pm
 | |
| index d711916..58c292a 100644
 | |
| --- a/lib/HTTP/Daemon.pm
 | |
| +++ b/lib/HTTP/Daemon.pm
 | |
| @@ -6,8 +6,10 @@ use warnings;
 | |
|  
 | |
|  our $VERSION = '6.04';
 | |
|  
 | |
| -use IO::Socket qw(AF_INET INADDR_ANY INADDR_LOOPBACK inet_ntoa);
 | |
| -our @ISA = qw(IO::Socket::INET);
 | |
| +use Socket qw(AF_INET AF_INET6 INADDR_ANY IN6ADDR_ANY
 | |
| +	    INADDR_LOOPBACK IN6ADDR_LOOPBACK inet_ntop sockaddr_family);
 | |
| +use IO::Socket::IP;
 | |
| +our @ISA = qw(IO::Socket::IP);
 | |
|  
 | |
|  our $PROTO = "HTTP/1.1";
 | |
|  
 | |
| @@ -42,15 +44,26 @@ sub url
 | |
|      my $self = shift;
 | |
|      my $url = $self->_default_scheme . "://";
 | |
|      my $addr = $self->sockaddr;
 | |
| -    if (!$addr || $addr eq INADDR_ANY) {
 | |
| +    if (!$addr || $addr eq INADDR_ANY || $addr eq IN6ADDR_ANY) {
 | |
|   	require Sys::Hostname;
 | |
|   	$url .= lc Sys::Hostname::hostname();
 | |
|      }
 | |
|      elsif ($addr eq INADDR_LOOPBACK) {
 | |
| -	$url .= inet_ntoa($addr);
 | |
| +	$url .= inet_ntop(AF_INET, $addr);
 | |
| +    }
 | |
| +    elsif ($addr eq IN6ADDR_LOOPBACK) {
 | |
| +	$url .= '[' . inet_ntop(AF_INET6, $addr) . ']';
 | |
|      }
 | |
|      else {
 | |
| -	$url .= gethostbyaddr($addr, AF_INET) || inet_ntoa($addr);
 | |
| +	my $host = $addr->sockhostname;
 | |
| +        if (!defined $host) {
 | |
| +	    if (sockaddr_family($addr) eq AF_INET6) {
 | |
| +		$host = '[' . inet_ntop(AF_INET6, $addr) . ']';
 | |
| +	    } else {
 | |
| +		$host = inet_ntop(AF_INET6, $addr);
 | |
| +	    }
 | |
| +	}
 | |
| +	$url .= $host;
 | |
|      }
 | |
|      my $port = $self->sockport;
 | |
|      $url .= ":$port" if $port != $self->_default_port;
 | |
| @@ -81,8 +94,8 @@ package  # hide from PAUSE
 | |
|  use strict;
 | |
|  use warnings;
 | |
|  
 | |
| -use IO::Socket ();
 | |
| -our @ISA = qw(IO::Socket::INET);
 | |
| +use IO::Socket::IP ();
 | |
| +our @ISA=qw(IO::Socket::IP);
 | |
|  our $DEBUG;
 | |
|  *DEBUG = \$HTTP::Daemon::DEBUG;
 | |
|  
 | |
| @@ -658,12 +671,12 @@ version 6.04
 | |
|  
 | |
|  Instances of the C<HTTP::Daemon> class are HTTP/1.1 servers that
 | |
|  listen on a socket for incoming requests. The C<HTTP::Daemon> is a
 | |
| -subclass of C<IO::Socket::INET>, so you can perform socket operations
 | |
| +subclass of C<IO::Socket::IP>, so you can perform socket operations
 | |
|  directly on it too.
 | |
|  
 | |
|  The accept() method will return when a connection from a client is
 | |
|  available.  The returned value will be an C<HTTP::Daemon::ClientConn>
 | |
| -object which is another C<IO::Socket::INET> subclass.  Calling the
 | |
| +object which is another C<IO::Socket::IP> subclass.  Calling the
 | |
|  get_request() method on this object will read data from the client and
 | |
|  return an C<HTTP::Request> object.  The ClientConn object also provide
 | |
|  methods to send back various responses.
 | |
| @@ -674,7 +687,7 @@ desirable.  Also note that the user is responsible for generating
 | |
|  responses that conform to the HTTP/1.1 protocol.
 | |
|  
 | |
|  The following methods of C<HTTP::Daemon> are new (or enhanced) relative
 | |
| -to the C<IO::Socket::INET> base class:
 | |
| +to the C<IO::Socket::IP> base class:
 | |
|  
 | |
|  =over 4
 | |
|  
 | |
| @@ -683,7 +696,7 @@ to the C<IO::Socket::INET> base class:
 | |
|  =item $d = HTTP::Daemon->new( %opts )
 | |
|  
 | |
|  The constructor method takes the same arguments as the
 | |
| -C<IO::Socket::INET> constructor, but unlike its base class it can also
 | |
| +C<IO::Socket::IP> constructor, but unlike its base class it can also
 | |
|  be called without any arguments.  The daemon will then set up a listen
 | |
|  queue of 5 connections and allocate some random port number.
 | |
|  
 | |
| @@ -695,7 +708,7 @@ HTTP port will be constructed like this:
 | |
|             LocalPort => 80,
 | |
|         );
 | |
|  
 | |
| -See L<IO::Socket::INET> for a description of other arguments that can
 | |
| +See L<IO::Socket::IP> for a description of other arguments that can
 | |
|  be used configure the daemon during construction.
 | |
|  
 | |
|  =item $c = $d->accept
 | |
| @@ -712,7 +725,7 @@ class a subclass of C<HTTP::Daemon::ClientConn>.
 | |
|  
 | |
|  The accept method will return C<undef> if timeouts have been enabled
 | |
|  and no connection is made within the given time.  The timeout() method
 | |
| -is described in L<IO::Socket>.
 | |
| +is described in L<IO::Socket::IP>.
 | |
|  
 | |
|  In list context both the client object and the peer address will be
 | |
|  returned; see the description of the accept method L<IO::Socket> for
 | |
| @@ -734,7 +747,7 @@ replaced with the version number of this module.
 | |
|  
 | |
|  =back
 | |
|  
 | |
| -The C<HTTP::Daemon::ClientConn> is a C<IO::Socket::INET>
 | |
| +The C<HTTP::Daemon::ClientConn> is a C<IO::Socket::IP>
 | |
|  subclass. Instances of this class are returned by the accept() method
 | |
|  of C<HTTP::Daemon>.  The following methods are provided:
 | |
|  
 | |
| @@ -908,7 +921,7 @@ Return a reference to the corresponding C<HTTP::Daemon> object.
 | |
|  
 | |
|  RFC 2616
 | |
|  
 | |
| -L<IO::Socket::INET>, L<IO::Socket>
 | |
| +L<IO::Socket::IP>, L<IO::Socket>
 | |
|  
 | |
|  =head1 SUPPORT
 | |
|  
 | |
| diff --git a/t/00-report-prereqs.dd b/t/00-report-prereqs.dd
 | |
| index 36929ec..1ec1f8a 100644
 | |
| --- a/t/00-report-prereqs.dd
 | |
| +++ b/t/00-report-prereqs.dd
 | |
| @@ -41,6 +41,7 @@ do { my $x = {
 | |
|                                        'HTTP::Response' => '6',
 | |
|                                        'HTTP::Status' => '6',
 | |
|                                        'IO::Socket' => '0',
 | |
| +                                      'IO::Socket::IP' => '0',
 | |
|                                        'LWP::MediaTypes' => '6',
 | |
|                                        'Sys::Hostname' => '0',
 | |
|                                        'perl' => '5.006',
 | |
| @@ -54,7 +55,7 @@ do { my $x = {
 | |
|                                     },
 | |
|                     'requires' => {
 | |
|                                     'File::Spec' => '0',
 | |
| -                                   'IO::Socket::INET' => '0',
 | |
| +                                   'IO::Socket::IP' => '0',
 | |
|                                     'Module::Metadata' => '0',
 | |
|                                     'Socket' => '0',
 | |
|                                     'Test' => '0',
 | |
| @@ -140,4 +141,4 @@ do { my $x = {
 | |
|                           }
 | |
|       };
 | |
|    $x;
 | |
| - }
 | |
| \ No newline at end of file
 | |
| + }
 | |
| diff --git a/t/chunked.t b/t/chunked.t
 | |
| index 14cab77..32594ec 100644
 | |
| --- a/t/chunked.t
 | |
| +++ b/t/chunked.t
 | |
| @@ -95,18 +95,30 @@ my $can_fork = $Config{d_fork} ||
 | |
|  my $tests = @TESTS;
 | |
|  my $tport = 8334;
 | |
|  
 | |
| -my $tsock = IO::Socket::INET->new(LocalAddr => '0.0.0.0',
 | |
| -                                  LocalPort => $tport,
 | |
| -                                  Listen    => 1,
 | |
| -                                  ReuseAddr => 1);
 | |
| +my @addresses = (
 | |
| +    { server => '::', client => '::1' },
 | |
| +    { server => '0.0.0.0', client => '127.0.0.1' }
 | |
| +);
 | |
| +my $family;
 | |
| +for my $id (0..$#addresses) {
 | |
| +    my $tsock = IO::Socket::IP->new(LocalAddr => $addresses[$id]->{server},
 | |
| +                                    LocalPort => $tport,
 | |
| +                                    Listen    => 1,
 | |
| +                                    ReuseAddr => 1);
 | |
| +    if ($tsock) {
 | |
| +        close $tsock;
 | |
| +        $family = $id;
 | |
| +        last;
 | |
| +    }
 | |
| +}
 | |
| +
 | |
|  if (!$can_fork) {
 | |
|    plan skip_all => "This system cannot fork";
 | |
|  }
 | |
| -elsif (!$tsock) {
 | |
| -  plan skip_all => "Cannot listen on 0.0.0.0:$tport";
 | |
| +elsif (!defined $family) {
 | |
| +  plan skip_all => "Cannot listen on unspecifed address and port $tport";
 | |
|  }
 | |
|  else {
 | |
| -  close $tsock;
 | |
|    plan tests => $tests;
 | |
|  }
 | |
|  
 | |
| @@ -132,9 +144,9 @@ if ($pid = fork) {
 | |
|        open my $fh, "| socket localhost $tport" or die;
 | |
|        print $fh $test;
 | |
|      }
 | |
| -    use IO::Socket::INET;
 | |
| -    my $sock = IO::Socket::INET->new(
 | |
| -                                     PeerAddr => "127.0.0.1",
 | |
| +    use IO::Socket::IP;
 | |
| +    my $sock = IO::Socket::IP->new(
 | |
| +                                     PeerAddr => $addresses[$family]->{client},
 | |
|                                       PeerPort => $tport,
 | |
|                                      ) or die;
 | |
|      if (0) {
 | |
| @@ -158,7 +170,7 @@ if ($pid = fork) {
 | |
|  } else {
 | |
|    die "cannot fork: $!" unless defined $pid;
 | |
|    my $d = HTTP::Daemon->new(
 | |
| -                            LocalAddr => '0.0.0.0',
 | |
| +                            LocalAddr => $addresses[$family]->{server},
 | |
|                              LocalPort => $tport,
 | |
|                              ReuseAddr => 1,
 | |
|                             ) or die;
 | |
| diff --git a/t/local/http.t b/t/local/http.t
 | |
| index 02006b0..91c03e8 100644
 | |
| --- a/t/local/http.t
 | |
| +++ b/t/local/http.t
 | |
| @@ -14,7 +14,7 @@ unless (-f "CAN_TALK_TO_OURSELF") {
 | |
|  
 | |
|  $| = 1; # autoflush
 | |
|  
 | |
| -require IO::Socket;  # make sure this work before we try to make a HTTP::Daemon
 | |
| +require Socket;  # make sure this work before we try to make a HTTP::Daemon
 | |
|  
 | |
|  # First we make ourself a daemon in another process
 | |
|  my $D = shift || '';
 | |
| diff --git a/t/robot/ua-get.t b/t/robot/ua-get.t
 | |
| index 87d8840..91b414a 100644
 | |
| --- a/t/robot/ua-get.t
 | |
| +++ b/t/robot/ua-get.t
 | |
| @@ -11,7 +11,7 @@ unless (-f "CAN_TALK_TO_OURSELF") {
 | |
|  }
 | |
|  
 | |
|  $| = 1; # autoflush
 | |
| -require IO::Socket;  # make sure this work before we try to make a HTTP::Daemon
 | |
| +require Socket;  # make sure this work before we try to make a HTTP::Daemon
 | |
|  
 | |
|  # First we make ourself a daemon in another process
 | |
|  my $D = shift || '';
 | |
| diff --git a/t/robot/ua.t b/t/robot/ua.t
 | |
| index eff7e37..1e87598 100644
 | |
| --- a/t/robot/ua.t
 | |
| +++ b/t/robot/ua.t
 | |
| @@ -11,7 +11,7 @@ unless (-f "CAN_TALK_TO_OURSELF") {
 | |
|  }
 | |
|  
 | |
|  $| = 1; # autoflush
 | |
| -require IO::Socket;  # make sure this work before we try to make a HTTP::Daemon
 | |
| +require Socket;  # make sure this work before we try to make a HTTP::Daemon
 | |
|  
 | |
|  # First we make ourself a daemon in another process
 | |
|  my $D = shift || '';
 | |
| -- 
 | |
| 2.20.1
 | |
| 
 |