--- Net-Server-0.99/lib/Net/Server/Proto/UDP.pm	2008-02-08 03:40:33.000000000 +0100
+++ lib/Net/Server/Proto/UDP.pm	2010-10-05 15:41:16.000000000 +0200
@@ -35,9 +35,4 @@
   my $class = ref($type) || $type || __PACKAGE__;
 
-  my $sock = $class->SUPER::object( @_ );
-
-  $sock->NS_proto('UDP');
-
-  ### set a few more parameters
   my($default_host,$port,$server) = @_;
   my $prop = $server->{server};
@@ -62,33 +57,42 @@
     && $prop->{udp_broadcast};
 
-  $sock->NS_recv_len(   $prop->{udp_recv_len} );
-  $sock->NS_recv_flags( $prop->{udp_recv_flags} );
+  my @sockets_list = $class->SUPER::object( @_ );
 
-  return $sock;
+  foreach my $sock ( @sockets_list ){
+    $sock->NS_proto('UDP');
+    $sock->NS_recv_len(   $prop->{udp_recv_len} );
+    $sock->NS_recv_flags( $prop->{udp_recv_flags} );
+  }
+
+  ### returns any number of sockets,
+  ### one for each protocol family (PF_INET or PF_INET6) and each bind address
+  return !wantarray ? $sockets_list[0] : @sockets_list;
 }
 
 
-### connect the first time
+### bind the first time
 ### doesn't support the listen or the reuse option
 sub connect {
-  my $sock   = shift;
-  my $server = shift;
-  my $prop   = $server->{server};
-
-  my $host  = $sock->NS_host;
-  my $port  = $sock->NS_port;
+  my $sock    = shift;
+  my $server  = shift;
+  my $prop    = $server->{server};
+
+  my $host    = $sock->NS_host;
+  my $port    = $sock->NS_port;
+  my $pfamily = $sock->NS_family || 0;
 
-  my %args = ();
+  my %args;
   $args{LocalPort} = $port;                  # what port to bind on
   $args{Proto}     = 'udp';                  # what procol to use
   $args{LocalAddr} = $host if $host !~ /\*/; # what local address (* is all)
+  $args{Domain} = $pfamily  if $Net::Server::Proto::TCP::have_inet6 && $pfamily;
   $args{Reuse}     = 1;  # allow us to rebind the port on a restart
   $args{Broadcast} = 1 if $prop->{udp_broadcast};
 
-  ### connect to the sock
+  ### bind to the sock
   $sock->SUPER::configure(\%args)
-    or $server->fatal("Can't connect to UDP port $port on $host [$!]");
+    or $server->fatal("Can't bind to UDP port $port on $host [$!]");
 
-  $server->fatal("Back sock [$!]!".caller())
+  $server->fatal("Bad sock [$!]!".caller())
     unless $sock;
 
--- Net-Server-0.99/lib/Net/Server/Proto.pm	2010-05-05 06:13:22.000000000 +0200
+++ lib/Net/Server/Proto.pm	2010-10-05 17:56:38.000000000 +0200
@@ -69,5 +69,6 @@
 
 
-  ### return an object of that procol class
+  ### returns any number of objects (socket),
+  ### one for each protocol family (PF_INET or PF_INET6) and each bind address
   return $proto_class->object($default_host,$port,$server);
 
@@ -84,5 +85,5 @@
 =head1 SYNOPSIS
 
-  # Net::Server::Proto and its accompianying modules are not
+  # Net::Server::Proto and its accompanying modules are not
   # intended to be used outside the scope of Net::Server.
 
@@ -103,5 +104,5 @@
   
   ### Net::Server::Proto will attempt to interface with
-  ### sub modules named simillar to Net::Server::Proto::TCP
+  ### sub modules named similar to Net::Server::Proto::TCP
   ### Individual sub modules will be loaded by
   ### Net::Server::Proto as they are needed.
@@ -225,8 +226,22 @@
 The port is the most important argument passed to the sub
 module classes and to Net::Server::Proto itself.  For tcp,
-udp, and ssl style ports, the form is generally
-host:port/protocol, host|port|protocol, host/port, or port.
-For unix the form is generally socket_file|type|unix or 
-socket_file.  
+udp, and ssl style ports, the form is generally host:port/protocol
+or [host]:port/protocol, host|port|protocol, host/port, or port.
+If I<host> is a numerical IPv6 address it must be enclosed in square
+brackets to avoid ambiguity in parsing a port number, e.g.: "[::1]:80".
+For unix sockets the form is generally socket_file|type|unix or socket_file.
+
+A socket protocol family PF_INET or PF_INET6 is derived from a specified
+address family of the binding address. A PF_INET socket can only accept
+IPv4 connections. A PF_INET6 socket accepts IPv6 connections, but may also
+accept IPv4 connections, depending on OS and its settings. For example,
+on FreeBSD systems setting a sysctl net.inet6.ip6.v6only to 0 will allow
+IPv4 connections to a PF_INET6 socket.
+
+The Net::Server::Proto::object method returns a list of objects corresponding
+to created sockets. For Unix and INET sockets the list typically contains
+just one element, but may return multiple objects when multiple protocol
+families are allowed or when a host name resolves to multiple local
+binding addresses.
 
 You can see what Net::Server::Proto parsed out by looking at
--- Net-Server-0.99/lib/Net/Server.pm	2010-07-09 16:55:31.000000000 +0200
+++ lib/Net/Server.pm	2010-10-05 19:52:16.000000000 +0200
@@ -26,5 +26,5 @@
 use strict;
 use vars qw($VERSION);
-use Socket qw(inet_aton inet_ntoa AF_INET AF_UNIX SOCK_DGRAM SOCK_STREAM);
+use Socket qw(AF_INET AF_UNIX SOCK_DGRAM SOCK_STREAM);
 use IO::Socket ();
 use IO::Select ();
@@ -356,6 +356,12 @@
   push @{ $prop->{host} }, (($prop->{host}->[-1]) x (@{ $prop->{port} } - @{ $prop->{host}})); # augment hosts with as many as port
   foreach my $host (@{ $prop->{host} }) {
-    $host = '*' if ! defined $host || ! length $host;;
-    $host = ($host =~ /^([\w\.\-\*\/]+)$/) ? $1 : $self->fatal("Unsecure host \"$host\"");
+    local $1;
+    if (!defined $host || $host eq '' || $host eq '*') {
+      $host = '*';
+    } elsif ($host =~ /^\[([\w\/.:-]+)\]$/ || $host =~ /^([\w\/.:-]+)$/) {
+      $host = $1;
+    } else {
+      $self->fatal("Unsecure host \"$host\"");
+    }
   }
 
@@ -377,10 +383,12 @@
     my $host  = $prop->{host}->[$i];
     my $proto = $prop->{proto}->[$i];
-    if ($port ne 0 && $bound{"$host/$port/$proto"}++) {
+    if ($port ne "0" && $bound{"$host/$port/$proto"}++) {
       $self->log(2, "Duplicate configuration (".(uc $proto)." port $port on host $host - skipping");
       next;
     }
-    my $obj = $self->proto_object($host, $port, $proto) || next;
-    push @{ $prop->{sock} }, $obj;
+    my @obj_list = $self->proto_object($host, $port, $proto);
+    for my $obj (@obj_list) {
+      push @{ $prop->{sock} }, $obj  if $obj;
+    }
   }
   if (! @{ $prop->{sock} }) {
@@ -397,5 +405,7 @@
 }
 
-### method for invoking procol specific bindings
+### method for invoking procol specific bindings;
+### returns any number of sockets,
+### one for each protocol family (PF_INET or PF_INET6) and each bind address
 sub proto_object {
   my $self = shift;
@@ -440,6 +450,8 @@
   }
 
-  ### if more than one port we'll need to select on it
-  if( @{ $prop->{port} } > 1 || $prop->{multi_port} ){
+  ### if more than one socket we'll need to select on it;
+  ### note there may be more than one socket per port,
+  ### one for each protocol family (PF_INET and PF_INET6)
+  if( @{ $prop->{sock} } > 1 || $prop->{multi_port} ){
     $prop->{multi_port} = 1;
     $prop->{select} = IO::Select->new();
@@ -748,5 +760,7 @@
     return;
   } elsif ($self->isa('Net::Server::INET')) {
-    $prop->{sockaddr} = $ENV{'REMOTE_HOST'} || '0.0.0.0';
+    # since we do not know a socket protocol family, we are unable
+    # to choose between '0.0.0.0' and '::' as an unspecified address
+    $prop->{sockaddr} = $ENV{'REMOTE_HOST'} || '0.0.0.0';  # or is is a '::' ?
     $prop->{peeraddr} = '0.0.0.0';
     $prop->{sockhost} = $prop->{peerhost} = 'inetd.server';
@@ -756,12 +770,12 @@
 
   ### read information about this connection
-  my $sockname = getsockname( $sock );
+  my $sockname = $sock->sockname;
   if( $sockname ){
-    ($prop->{sockport}, $prop->{sockaddr})
-      = Socket::unpack_sockaddr_in( $sockname );
-    $prop->{sockaddr} = inet_ntoa( $prop->{sockaddr} );
-
+    $prop->{sockaddr} = $sock->sockhost;
+    $prop->{sockport} = $sock->sockport;
   }else{
     ### does this only happen from command line?
+    # since we do not know a socket protocol family, we are unable
+    # to choose between '0.0.0.0' and '::' as an unspecified address
     $prop->{sockaddr} = $ENV{'REMOTE_HOST'} || '0.0.0.0';
     $prop->{sockhost} = 'inet.test';
@@ -773,16 +787,24 @@
   if( $prop->{udp_true} ){
     $proto_type = 'UDP';
-    ($prop->{peerport} ,$prop->{peeraddr})
-      = Socket::sockaddr_in( $prop->{udp_peer} );
-  }elsif( $prop->{peername} = getpeername( $sock ) ){
-    ($prop->{peerport}, $prop->{peeraddr})
-      = Socket::unpack_sockaddr_in( $prop->{peername} );
-  }
-
-  if( $prop->{peername} || $prop->{udp_true} ){
-    $prop->{peeraddr} = inet_ntoa( $prop->{peeraddr} );
-
-    if( defined $prop->{reverse_lookups} ){
-      $prop->{peerhost} = gethostbyaddr( inet_aton($prop->{peeraddr}), AF_INET );
+    if ($sock->sockdomain == AF_INET) { ($prop->{peerport}, $prop->{peeraddrn}) = Socket::sockaddr_in($prop->{udp_peer});
+    } else { ($prop->{peerport}, $prop->{peeraddrn}) = Socket6::sockaddr_in6($prop->{udp_peer});
+    }
+    $prop->{peeraddr} = Socket6->UNIVERSAL::can('inet_ntop')
+                   ? Socket6::inet_ntop($sock->sockdomain, $prop->{peeraddrn})
+                   : Socket::inet_ntoa( $prop->{peeraddrn} );
+  }elsif( $prop->{peername} = $sock->peername ){
+    $prop->{peeraddrn} = $sock->peeraddr;  # binary
+    $prop->{peeraddr} = $sock->peerhost;   # ascii
+    $prop->{peerport} = $sock->peerport;
+  }
+
+  if( $prop->{peeraddrn} ){
+    if( !defined $prop->{reverse_lookups} ){
+      # no reverse DNS resolving
+    }elsif( Socket6->UNIVERSAL::can('getnameinfo') ){
+      my @res = Socket6::getnameinfo( $prop->{peeraddrn}, 0 );
+      $prop->{peerhost} = $res[0]  if @res > 1;
+    }else{
+      $prop->{peerhost} = gethostbyaddr( $prop->{peeraddrn}, AF_INET );
     }
     $prop->{peerhost} = '' unless defined $prop->{peerhost};
@@ -790,4 +812,6 @@
   }else{
     ### does this only happen from command line?
+    # since we do not know a socket protocol family, we are unable
+    # to choose between '0.0.0.0' and '::' as an unspecified address
     $prop->{peeraddr} = '0.0.0.0';
     $prop->{peerhost} = 'inet.test';
@@ -796,6 +820,6 @@
 
   $self->log(3,$self->log_time
-             ." CONNECT $proto_type Peer: \"$prop->{peeraddr}:$prop->{peerport}\""
-             ." Local: \"$prop->{sockaddr}:$prop->{sockport}\"\n");
+             ." CONNECT $proto_type Peer: \"[$prop->{peeraddr}]:$prop->{peerport}\""
+             ." Local: \"[$prop->{sockaddr}]:$prop->{sockport}\"\n");
 
 }
@@ -1141,9 +1165,11 @@
   foreach my $sock ( @{ $prop->{sock} } ){
 
-    ### duplicate the sock
+    ### duplicate the socket descriptor
     my $fd = POSIX::dup($sock->fileno)
       or $self->fatal("Can't dup socket [$!]");
 
-    ### hold on to the socket copy until exec
+    ### hold on to the socket copy until exec;
+    ### just temporary: any socket domain will do,
+    ### forked process will decide to use IO::Socket::INET6 if necessary
     $prop->{_HUP}->[$i] = IO::Socket::INET->new;
     $prop->{_HUP}->[$i]->fdopen($fd, 'w')
@@ -1153,5 +1179,5 @@
     $prop->{_HUP}->[$i]->fcntl( Fcntl::F_SETFD(), my $flags = "" );
 
-    ### save host,port,proto, and file descriptor
+    ### save file descriptor and host|port|proto|family
     push @fd, $fd .'|'. $sock->hup_string;
 
--- Net-Server-0.99/lib/Net/Server.pod	2010-07-08 21:22:42.000000000 +0200
+++ lib/Net/Server.pod	2010-10-05 19:32:28.000000000 +0200
@@ -556,19 +556,46 @@
 bound at server startup.  May be of the form
 C<host:port/proto>, C<host:port>, C<port/proto>, or C<port>,
-where I<host> represents a hostname residing on the local
-box, where I<port> represents either the number of the port
-(eg. "80") or the service designation (eg.  "http"), and
-where I<proto> represents the protocol to be used.  See
-L<Net::Server::Proto>.  If you are working with unix sockets,
-you may also specify C<socket_file|unix> or
-C<socket_file|type|unix> where type is SOCK_DGRAM or
-SOCK_STREAM.  If the protocol is not specified, I<proto> will
+where I<host> represents a hostname residing on the local box,
+where I<port> represents either the number of the port (eg. "80")
+or the service designation (eg. "http"), and where I<proto>
+represents the protocol to be used. See L<Net::Server::Proto>.
+
+An explicit I<host> given in a port specification overrides
+a default binding address (a C<host> setting, see below).
+The I<host> part may be enclosed in square brackets, but when it is
+a numerical IPv6 address it B<must> be enclosed in square brackets
+to avoid ambiguity in parsing a port number, e.g.: "[::1]:80".
+
+If you are working with unix sockets, you may also specify
+C<socket_file|unix> or C<socket_file|type|unix> where type is SOCK_DGRAM
+or SOCK_STREAM.  If the protocol is not specified, I<proto> will
 default to the C<proto> specified in the arguments.  If C<proto> is not
 specified there it will default to "tcp".  If I<host> is not
 specified, I<host> will default to C<host> specified in the
-arguments.  If C<host> is not specified there it will
-default to "*".  Default port is 20203.  Configuration passed
-to new or run may be either a scalar containing a single port
-number or an arrayref of ports.
+arguments.  If C<host> is not specified there it will default to "*".
+Default port is 20203.  Configuration passed to new or run may be either
+a scalar containing a single port number or an arrayref of ports.
+
+On an IPv6-enabled host where a module IO::Socket::INET6 is installed
+the "*" implies two listening sockets, one for each of the protocols
+(PF_INET and PF_INET6) and is equivalent to specifying two ports, bound
+to an 'unspecified' address of each address family ("0.0.0.0" and "::").
+If listening on an INET6 socket is not desired despite IO::Socket::INET6
+module being available, please supply the 'unspecifed' INET (IPv4) address
+'0.0.0.0' as a I<host>, either in the C<port> or in the C<host> argument.
+
+An INET socket can only accept IPv4 connections. An INET6 socket accepts
+IPv6 connections, but may also accept IPv4 connections depending on
+OS and its settings. For example, on FreeBSD systems setting a sysctl
+net.inet6.ip6.v6only to 0 will allow IPv4 connections to an INET6 socket.
+If this is the case, specifying "::" as a binding address instead of a "*"
+might be desired to reduce the number of sockets needed. Note that a
+textual representation of a peer's IPv4 address as connected to an INET6
+socket will typically be in a form of an IPv4-mapped IPv6 addresses,
+e.g. "::FFFF:127.0.0.1" .
+
+Restricting binding to a loopback interface on systems where an INET6
+socket does not accept IPv4 connections requires creating two sockets,
+one bound to address "127.0.0.1" and the other bound to address "::1".
 
 On systems that support it, a port value of 0 may be used to ask
@@ -583,5 +610,7 @@
 Local host or addr upon which to bind port.  If a value of '*' is
 given, the server will bind that port on all available addresses
-on the box.  See L<Net::Server::Proto>. See L<IO::Socket>.  Configuration
+on the box.  The C<host> argument provides a default local host
+address if the C<port> argument omits a host specification.
+See L<Net::Server::Proto>. See L<IO::Socket>.  Configuration
 passed to new or run may be either a scalar containing a single
 host or an arrayref of hosts - if the hosts array is shorter than
--- Net-Server-0.99/lib/Net/Server/Proto/SSLEAY.pm.orig	2010-07-09 09:44:48.000000000 -0700
+++ lib/Net/Server/Proto/SSLEAY.pm	2011-08-01 11:08:19.183613424 -0700
@@ -22,156 +22,254 @@
 package Net::Server::Proto::SSLEAY;
 
 use strict;
-use vars qw($VERSION $AUTOLOAD @ISA);
-use IO::Socket::INET;
+use vars qw($VERSION $AUTOLOAD @ISA $have_inet6);
 use Fcntl ();
 use Errno ();
 use Socket ();
+use IO::Socket;
 
 BEGIN {
-    eval { require Net::SSLeay };
-    $@ && warn "Module Net::SSLeay is required for SSLeay.";
-    # Net::SSLeay gets mad if we call these multiple times - the question is - who will call them multiple times?
-    for my $sub (qw(load_error_strings SSLeay_add_ssl_algorithms ENGINE_load_builtin_engines ENGINE_register_all_complete randomize)) {
-        Net::SSLeay->can($sub)->();
-    }
+  eval {
+    require Socket6; import Socket6;
+    require IO::Socket::INET6;
+    @ISA = qw(IO::Socket::INET6);
+    $have_inet6 = 1;
+  } or do {
+    require IO::Socket::INET;
+    @ISA = qw(IO::Socket::INET);
+  };
+  eval { require Net::SSLeay };
+  $@ && warn "Module Net::SSLeay is required for SSLeay.";
+  # Net::SSLeay gets mad if we call these multiple times - the question is - who will call them multiple times?
+  for my $sub (qw(load_error_strings SSLeay_add_ssl_algorithms ENGINE_load_builtin_engines ENGINE_register_all_complete randomize)) {
+    Net::SSLeay->can($sub)->();
+  }
 }
 
 $VERSION = $Net::Server::VERSION; # done until separated
-@ISA = qw(IO::Socket::INET);
+
+# additional protocol specific arguments
+my @ssl_args = qw(
+    SSL_use_cert
+    SSL_verify_mode
+    SSL_key_file
+    SSL_cert_file
+    SSL_ca_path
+    SSL_ca_file
+    SSL_cipher_list
+    SSL_passwd_cb
+    SSL_max_getline_length
+    SSL_error_callback
+);
 
 sub object {
-    my $type  = shift;
-    my $class = ref($type) || $type || __PACKAGE__;
+  my $type  = shift;
+  my $class = ref($type) || $type || __PACKAGE__;
 
-    my ($default_host,$port,$server) = @_;
-    my $prop = $server->{'server'};
-    my $host;
-
-    if ($port =~ m/^([\w\.\-\*\/]+):(\w+)$/) { # allow for things like "domain.com:80"
-        ($host, $port) = ($1, $2);
-    }
-    elsif ($port =~ /^(\w+)$/) { # allow for things like "80"
-        ($host, $port) = ($default_host, $1);
-    }
-    else {
-        $server->fatal("Undeterminate port \"$port\" under ".__PACKAGE__);
-    }
-
-    # read any additional protocol specific arguments
-    my @ssl_args = qw(
-        SSL_server
-        SSL_use_cert
-        SSL_verify_mode
-        SSL_key_file
-        SSL_cert_file
-        SSL_ca_path
-        SSL_ca_file
-        SSL_cipher_list
-        SSL_passwd_cb
-        SSL_error_callback
-        SSL_max_getline_length
-    );
-    my %args;
-    $args{$_} = \$prop->{$_} for @ssl_args;
-    $server->configure(\%args);
-
-    my $sock = $class->new;
-    $sock->NS_host($host);
-    $sock->NS_port($port);
-    $sock->NS_proto('SSLEAY');
+  my ($default_host,$port,$server) = @_;
+  my $host;
+  my $prop = $server->{'server'};
+
+  local($1,$2);
+  ### allow for things like "[::1]:80" or "[host.example.com]:80"
+  if( $port =~ m/^\[([^\]]*)\]:(\w+)$/ ){
+    ($host,$port) = ($1,$2);
+
+  ### allow for things like "host.example.com:80"
+  }elsif( $port =~ m/^([\w\.\-\*\/]+):(\w+)$/ ){
+    ($host,$port) = ($1,$2);
+
+  ### allow for things like "80" or "http"
+  }elsif( $port =~ /^(\w+)$/ ){
+    ($host,$port) = ($default_host,$1);
+
+  ### don't know that style of port
+  }else{
+    $server->fatal("Undeterminate port \"$port\" under ".__PACKAGE__);
+  }
+
+  ### collect bind addresses along with their address family for all hosts
+  my @bind_tuples;
+  if( $host =~ /^\d{1,3}(?:\.\d{1,3}){3}\z/ ){
+    push(@bind_tuples, [AF_INET,$host,$port]);
+  }elsif( $host =~ /:/ ){
+    die "No IO::Socket::INET6, cannot bind to [$host]:$port"  if !$have_inet6;
+    push(@bind_tuples, [AF_INET6,$host,$port]);
+  }elsif( !$have_inet6 ){
+    push(@bind_tuples, [AF_INET,$host,$port]);
+  }elsif( $have_inet6 && $host =~ /\*/ ){
+    push(@bind_tuples, [AF_INET6,$host,$port], [AF_INET,$host,$port]);
+  }else{  # we do have IO::Socket::INET6, it handles inet6 as well as inet
+    # obtain a list of IP addresses for $host, resolve port name
+    my @res1 = getaddrinfo($host, $port, AF_UNSPEC, SOCK_STREAM, 0,
+                           AI_PASSIVE|AI_ADDRCONFIG);
+    die "Unresolvable [$host]:$port: $res1[0]"  if @res1 < 5;
+    while (@res1 >= 5) {
+      my($afam, $socktype, $proto, $saddr, $canonname);
+      ($afam, $socktype, $proto, $saddr, $canonname, @res1) = @res1;
+      my @res2 = getnameinfo($saddr, NI_NUMERICHOST | NI_NUMERICSERV);
+      die "getnameinfo failed on [$host]:$port: $res2[0]"  if @res2 < 2;
+      my($hostip,$portnum) = @res2;
+      $server->log(4,"Resolved [$host]:$port -> [$hostip]:$portnum, AF $afam");
+      push(@bind_tuples, [$afam,$hostip,$portnum]);
+    }
+  }
+
+  my @sockets_list;
+  ### create a socket for each specified bind address and family
+  foreach my $tuple ( @bind_tuples ){
+    my $afamily;  # address family (AF_* constants)
+    my $pfamily;  # socket protocol family (PF_* constants)
+    ($afamily,$host,$port) = @$tuple;
+    my $sock;
+    if( $have_inet6 ){
+      # Using IO::Socket::INET6 to handle both the IPv4 and IPv6.
+      # Constants PF_INET/PF_INET6 (protocol family) usually happen to have
+      # the same value as AF_INET/AF_INET6 (address family) constants.
+      # Still, better safe than sorry:
+      if ( $afamily == AF_INET ) {
+        $pfamily = PF_INET;
+      } elsif ( $afamily == AF_INET6 ) {
+        $pfamily = PF_INET6;
+      } else {
+        $pfamily = $afamily;
+      }
+      $server->log(3,"Using IO::Socket::INET6 for [$host]:$port, PF $pfamily");
+      $sock = IO::Socket::INET6->new(Domain => $pfamily);  # inet or inet6
+    }else{
+      $pfamily = PF_INET;
+      $server->log(3,"Using IO::Socket::INET for [$host]:$port, PF $pfamily");
+      $sock = IO::Socket::INET->new();  # inet socket (IPv4 only)
+    }
+
+    if ($sock) {
+      bless $sock, $class;
+
+      $sock->NS_host($host);
+      $sock->NS_port($port);
+      $sock->NS_proto('SSLEAY');
+      $sock->NS_family($pfamily);  # socket protocol family
 
-    for my $key (@ssl_args) {
+      for my $key (@ssl_args) {
         my $val = defined($prop->{$key}) ? $prop->{$key} : $server->can($key) ? $server->$key($host, $port, 'SSLEAY') : undef;
         $sock->$key($val);
+      }
+      push @sockets_list, $sock;
     }
+  }
 
-    return $sock;
+  ### returns any number of sockets,
+  ### one for each protocol family (PF_INET or PF_INET6) and each bind address
+  return !wantarray ? $sockets_list[0] : @sockets_list;
 }
 
 sub log_connect {
-    my $sock = shift;
-    my $server = shift;
-    my $host   = $sock->NS_host;
-    my $port   = $sock->NS_port;
-    my $proto  = $sock->NS_proto;
-    $server->log(2,"Binding to $proto port $port on host $host\n");
+  my $sock = shift;
+  my $server  = shift;
+  my $host    = $sock->NS_host; 
+  my $port    = $sock->NS_port;
+  my $proto   = $sock->NS_proto;
+  my $pfamily = $sock->NS_family || 0;
+  $server->log(2,"Binding to $proto port $port on host $host, PF $pfamily\n");
 }
 
 ###----------------------------------------------------------------###
 
-sub connect { # connect the first time
-    my $sock   = shift;
-    my $server = shift;
-    my $prop   = $server->{'server'};
-
-    my $host  = $sock->NS_host;
-    my $port  = $sock->NS_port;
-
-    my %args;
-    $args{'LocalPort'} = $port;
-    $args{'Proto'}     = 'tcp';
-    $args{'LocalAddr'} = $host if $host !~ /\*/; # * is all
-    $args{'Listen'}    = $prop->{'listen'};
-    $args{'Reuse'}     = 1;
-
-    $sock->SUPER::configure(\%args) || $server->fatal("Can't connect to SSL port $port on $host [$!]");
-    $server->fatal("Bad sock [$!]!".caller()) if ! $sock;
-
-    if ($port == 0 && ($port = $sock->sockport)) {
-        $sock->NS_port($port);
-        $server->log(2,"Bound to auto-assigned port $port");
-    }
-
-    $sock->bind_SSL($server);
-}
-
-sub reconnect { # connect on a sig -HUP
-    my ($sock, $fd, $server) = @_;
-    my $resp = $sock->fdopen( $fd, 'w' ) || $server->fatal("Error opening to file descriptor ($fd) [$!]");
-    $sock->bind_SSL($server);
-    return $resp;
+### bind the first time
+sub connect {
+  my $sock    = shift;
+  my $server  = shift;
+  my $prop    = $server->{server};
+
+  my $host    = $sock->NS_host;
+  my $port    = $sock->NS_port;
+  my $pfamily = $sock->NS_family || 0;
+
+  my %args;
+  $args{LocalPort} = $port;
+  $args{Proto}     = 'tcp';
+  $args{LocalAddr} = $host if $host !~ /\*/;  # * is all
+  $args{Domain}    = $pfamily  if $have_inet6 && $pfamily;
+  $args{Listen}    = $prop->{listen};
+  $args{Reuse}     = 1;
+
+  $sock->SUPER::configure(\%args)
+    or $server->fatal("Can't bind to SSL port $port on $host [$!]");
+  $server->fatal("Bad sock [$!]!".caller())  if !$sock;
+
+  my $actual_port = $sock->sockport;
+  # $port may be a service name, compare as strings
+  if( $actual_port && (!defined $port || $actual_port ne $port) ){
+    $sock->NS_port($actual_port);
+    if( $port =~ /^0*\z/ ){
+      $server->log(2,"Bound to auto-assigned port $actual_port");
+    }else{
+      $server->log(3,"Bound to service \"$port\", port number $actual_port");
+    }
+  }
+
+  $sock->bind_SSL($server);
+}
+
+### reassociate sockets with inherited file descriptors on a sig -HUP
+sub reconnect {
+  my ($sock, $fd, $server) = @_;
+
+  my $host    = $sock->NS_host; 
+  my $port    = $sock->NS_port;
+  my $proto   = $sock->NS_proto;
+  my $pfamily = $sock->NS_family || 0;
+
+  $server->log(3,"Reassociating file descriptor $fd ".
+                 "with socket $proto on [$host]:port, PF $pfamily\n");
+  my $resp = $sock->fdopen( $fd, 'w' )
+    or $server->fatal("Error opening to file descriptor ($fd) [$!]");
+  $sock->bind_SSL($server);
+  return $resp;
 }
 
 sub bind_SSL {
-    my ($sock, $server) = @_;
-    my $ctx = Net::SSLeay::CTX_new();  $sock->SSLeay_check_fatal("SSLeay bind_SSL CTX_new");
+  my ($sock, $server) = @_;
+  my $ctx = Net::SSLeay::CTX_new();  $sock->SSLeay_check_fatal("SSLeay bind_SSL CTX_new");
 
-    Net::SSLeay::CTX_set_options($ctx, Net::SSLeay::OP_ALL());  $sock->SSLeay_check_fatal("SSLeay bind_SSL CTX_set_options");
+  Net::SSLeay::CTX_set_options($ctx, Net::SSLeay::OP_ALL());  $sock->SSLeay_check_fatal("SSLeay bind_SSL CTX_set_options");
 
-    # 0x1:  SSL_MODE_ENABLE_PARTIAL_WRITE
-    # 0x10: SSL_MODE_RELEASE_BUFFERS (ignored before OpenSSL v1.0.0)
-    Net::SSLeay::CTX_set_mode($ctx, 0x11);  $sock->SSLeay_check_fatal("SSLeay bind_SSL CTX_set_mode");
-
-    # Load certificate. This will prompt for a password if necessary.
-    my $file_key  = $sock->SSL_key_file  || die "SSLeay missing SSL_key_file.\n";
-    my $file_cert = $sock->SSL_cert_file || die "SSLeay missing SSL_cert_file.\n";
-    Net::SSLeay::CTX_use_RSAPrivateKey_file($ctx, $file_key,  Net::SSLeay::FILETYPE_PEM());  $sock->SSLeay_check_fatal("SSLeay bind_SSL CTX_use_RSAPrivateKey_file");
-    Net::SSLeay::CTX_use_certificate_file(  $ctx, $file_cert, Net::SSLeay::FILETYPE_PEM());  $sock->SSLeay_check_fatal("SSLeay bind_SSL CTX_use_certificate_file");
-    $sock->SSLeay_context($ctx);
+  # 0x1:  SSL_MODE_ENABLE_PARTIAL_WRITE
+  # 0x10: SSL_MODE_RELEASE_BUFFERS (ignored before OpenSSL v1.0.0)
+  Net::SSLeay::CTX_set_mode($ctx, 0x11);  $sock->SSLeay_check_fatal("SSLeay bind_SSL CTX_set_mode");
+
+  # Load certificate. This will prompt for a password if necessary.
+  my $file_key  = $sock->SSL_key_file  || die "SSLeay missing SSL_key_file.\n";
+  my $file_cert = $sock->SSL_cert_file || die "SSLeay missing SSL_cert_file.\n";
+  Net::SSLeay::CTX_use_RSAPrivateKey_file($ctx, $file_key,  Net::SSLeay::FILETYPE_PEM());  $sock->SSLeay_check_fatal("SSLeay bind_SSL CTX_use_RSAPrivateKey_file");
+  Net::SSLeay::CTX_use_certificate_file(  $ctx, $file_cert, Net::SSLeay::FILETYPE_PEM());  $sock->SSLeay_check_fatal("SSLeay bind_SSL CTX_use_certificate_file");
+  $sock->SSLeay_context($ctx);
 }
 
 sub close {
-    my $sock = shift;
-    if ($sock->SSLeay_is_client) {
-        Net::SSLeay::free($sock->SSLeay);
-    } else {
-        Net::SSLeay::CTX_free($sock->SSLeay_context);
-    }
-    $sock->SSLeay_check_fatal("SSLeay close free");
-    return $sock->SUPER::close(@_);
+  my $sock = shift;
+  if ($sock->SSLeay_is_client) {
+    Net::SSLeay::free($sock->SSLeay);
+  } else {
+    Net::SSLeay::CTX_free($sock->SSLeay_context);
+  }
+  $sock->SSLeay_check_fatal("SSLeay close free");
+  return $sock->SUPER::close(@_);
 }
 
 sub accept {
-    my $sock = shift;
-    my $client = $sock->SUPER::accept;
-    if (defined $client) {
-        $client->NS_proto($sock->NS_proto);
-        $client->SSLeay_context($sock->SSLeay_context);
-        $client->SSLeay_is_client(1);
-    }
+  my $sock = shift;
+  my $client = $sock->SUPER::accept;
+  if (defined $client) {
+    $client->NS_proto( $sock->NS_proto );
+    $client->NS_family( $sock->NS_family );
+    $client->NS_host( $sock->NS_host );
+    $client->NS_port( $sock->NS_port );
+    $client->SSLeay_context( $sock->SSLeay_context );
+    $client->SSLeay_is_client(1);
+  }
 
-    return $client;
+  return $client;
 }
 
 sub SSLeay {
@@ -280,6 +378,17 @@
     return length $read;
 }
 
+sub sysread {
+    my ($client, $buf, $size, $offset) = @_;
+    warn "sysread is not supported by Net::Server::Proto::SSLEAY";
+    # not quite right, usable only for testing:
+    my ($ok, $read) = $client->read_until($size, $/, 1);
+    substr($_[1], $offset || 0, defined($buf) ? length($buf) : 0, $read);
+    # should return the number of bytes actually read, 0 at end of file, or
+    # undef if there was an error (in the latter case $! should also be set)
+    return length $read;
+}
+
 sub getline {
     my $client = shift;
     my ($ok, $line) = $client->read_until($client->SSL_max_getline_length, $/);
@@ -330,20 +439,24 @@
     $client->print($buf);
 }
 
-sub sysread  { die "sysread is not supported by Net::Server::Proto::SSLEAY" }
 sub syswrite { die "syswrite is not supported by Net::Server::Proto::SSLEAY" }
 
 ###----------------------------------------------------------------###
 
 sub hup_string {
     my $sock = shift;
-    return join "|", map{$sock->$_()} qw(NS_host NS_port NS_proto);
+    return join("|",
+                $sock->NS_host,
+                $sock->NS_port,
+                $sock->NS_proto,
+                !$have_inet6 || !$sock->NS_family ? () : $sock->NS_family,
+              );
 }
 
 sub show {
     my $sock = shift;
     my $t = "Ref = \"" .ref($sock) . "\"\n";
-    foreach my $prop ( qw(NS_proto NS_port NS_host SSLeay_context SSLeay_is_client) ){
+    foreach my $prop ( qw(NS_proto NS_port NS_host NS_family SSLeay_context SSLeay_is_client) ){
         $t .= "  $prop = \"" .$sock->$prop()."\"\n";
     }
     return $t;
@@ -353,7 +466,7 @@
     my $sock = shift;
     my $prop = $AUTOLOAD =~ /::([^:]+)$/ ? $1 : die "Missing property in AUTOLOAD.";
     die "Unknown method or property [$prop]"
-        if $prop !~ /^(NS_proto|NS_port|NS_host|SSLeay_context|SSLeay_is_client|SSL_\w+)$/;
+        if $prop !~ /^(NS_proto|NS_port|NS_host|NS_family|SSLeay_context|SSLeay_is_client|SSL_\w+)$/;
 
     no strict 'refs';
     *{__PACKAGE__."::${prop}"} = sub {
--- Net-Server-0.99/lib/Net/Server/Proto/SSL.pm.orig	2010-05-04 20:13:03.000000000 -0700
+++ lib/Net/Server/Proto/SSL.pm	2011-08-01 11:08:50.503627241 -0700
@@ -22,14 +22,47 @@
 package Net::Server::Proto::SSL;
 
 use strict;
-use vars qw($VERSION $AUTOLOAD @ISA);
-use Net::Server::Proto::TCP ();
-eval { require IO::Socket::SSL; };
-$@ && warn "Module IO::Socket::SSL is required for SSL.";
+use vars qw($VERSION $AUTOLOAD @ISA $have_inet6 $io_socket_module);
+use IO::Socket;
+
+BEGIN {
+  eval {
+    require Socket6; import Socket6;
+    require IO::Socket::INET6;
+    $io_socket_module = 'IO::Socket::INET6';
+    $have_inet6 = 1;
+  } or do {
+    require IO::Socket::INET;
+    $io_socket_module = 'IO::Socket::INET';
+  };
+  @ISA = ( $io_socket_module );
+}
+
+eval {
+  require IO::Socket::SSL; import IO::Socket::SSL;
+  # we could add IO::Socket::SSL to a local copy of @ISA just before calling
+  # start_SSL and do away with the $io_socket_module trick later, but this
+  # causes perl 5.12.2 to crash, so do it the way it likes it
+  unshift(@ISA, qw(IO::Socket::SSL));  1;
+} or do {
+  warn "Module IO::Socket::SSL is required for SSL: $@";
+};
 
 $VERSION = $Net::Server::VERSION; # done until separated
-@ISA = qw(IO::Socket::SSL);
 
+# additional protocol specific arguments
+my @ssl_args = qw(
+    SSL_use_cert
+    SSL_verify_mode
+    SSL_key_file
+    SSL_cert_file
+    SSL_ca_path
+    SSL_ca_file
+    SSL_cipher_list
+    SSL_passwd_cb
+    SSL_max_getline_length
+    SSL_error_callback
+);
 
 sub object {
   my $type  = shift;
@@ -39,11 +72,16 @@
   my $prop = $server->{server};
   my $host;
 
-  ### allow for things like "domain.com:80"
-  if( $port =~ m/^([\w\.\-\*\/]+):(\w+)$/ ){
+  local($1,$2);
+  ### allow for things like "[::1]:80" or "[host.example.com]:80"
+  if( $port =~ m/^\[([^\]]*)\]:(\w+)$/ ){
     ($host,$port) = ($1,$2);
 
-  ### allow for things like "80"
+  ### allow for things like "host.example.com:80"
+  }elsif( $port =~ m/^([\w\.\-\*\/]+):(\w+)$/ ){
+    ($host,$port) = ($1,$2);
+
+  ### allow for things like "80" or "http"
   }elsif( $port =~ /^(\w+)$/ ){
     ($host,$port) = ($default_host,$1);
 
@@ -52,98 +90,167 @@
     $server->fatal("Undeterminate port \"$port\" under ".__PACKAGE__);
   }
 
-  # read any additional protocol specific arguments
-  my @ssl_args = qw(
-      SSL_server
-      SSL_use_cert
-      SSL_verify_mode
-      SSL_key_file
-      SSL_cert_file
-      SSL_ca_path
-      SSL_ca_file
-      SSL_cipher_list
-      SSL_passwd_cb
-      SSL_max_getline_length
-  );
-  my %args;
-  $args{$_} = \$prop->{$_} for @ssl_args;
-  $server->configure(\%args);
-
-  my $sock = $class->new;
-  $sock->NS_host($host);
-  $sock->NS_port($port);
-  $sock->NS_proto('SSL');
+  ### collect bind addresses along with their address family for all hosts
+  my @bind_tuples;
+  if( $host =~ /^\d{1,3}(?:\.\d{1,3}){3}\z/ ){
+    push(@bind_tuples, [AF_INET,$host,$port]);
+  }elsif( $host =~ /:/ ){
+    die "No IO::Socket::INET6, cannot bind to [$host]:$port"  if !$have_inet6;
+    push(@bind_tuples, [AF_INET6,$host,$port]);
+  }elsif( !$have_inet6 ){
+    push(@bind_tuples, [AF_INET,$host,$port]);
+  }elsif( $have_inet6 && $host =~ /\*/ ){
+    push(@bind_tuples, [AF_INET6,$host,$port], [AF_INET,$host,$port]);
+  }else{  # we do have IO::Socket::INET6, it handles inet6 as well as inet
+    # obtain a list of IP addresses for $host, resolve port name
+    my @res1 = getaddrinfo($host, $port, AF_UNSPEC, SOCK_STREAM, 0,
+                           AI_PASSIVE|AI_ADDRCONFIG);
+    die "Unresolvable [$host]:$port: $res1[0]"  if @res1 < 5;
+    while (@res1 >= 5) {
+      my($afam, $socktype, $proto, $saddr, $canonname);
+      ($afam, $socktype, $proto, $saddr, $canonname, @res1) = @res1;
+      my @res2 = getnameinfo($saddr, NI_NUMERICHOST | NI_NUMERICSERV);
+      die "getnameinfo failed on [$host]:$port: $res2[0]"  if @res2 < 2;
+      my($hostip,$portnum) = @res2;
+      $server->log(4,"Resolved [$host]:$port -> [$hostip]:$portnum, AF $afam");
+      push(@bind_tuples, [$afam,$hostip,$portnum]);
+    }
+  }
 
-  for my $key (@ssl_args) {
-    my $val = defined($prop->{$key}) ? $prop->{$key} : $server->can($key) ? $server->$key($host, $port, 'SSL') : undef;
-    $sock->$key($val);
+  my @sockets_list;
+  ### create a socket for each specified bind address and family
+  foreach my $tuple ( @bind_tuples ){
+    my $afamily;  # address family (AF_* constants)
+    my $pfamily;  # socket protocol family (PF_* constants)
+    ($afamily,$host,$port) = @$tuple;
+    my $sock;
+    if( $have_inet6 ){
+      # Using IO::Socket::INET6 to handle both the IPv4 and IPv6.
+      # Constants PF_INET/PF_INET6 (protocol family) usually happen to have
+      # the same value as AF_INET/AF_INET6 (address family) constants.
+      # Still, better safe than sorry:
+      if ( $afamily == AF_INET ) {
+        $pfamily = PF_INET;
+      } elsif ( $afamily == AF_INET6 ) {
+        $pfamily = PF_INET6;
+      } else {
+        $pfamily = $afamily;
+      }
+      $server->log(3,"Using IO::Socket::INET6 for [$host]:$port, PF $pfamily");
+      $sock = IO::Socket::INET6->new(Domain => $pfamily);  # inet or inet6
+    }else{
+      $pfamily = PF_INET;
+      $server->log(3,"Using IO::Socket::INET for [$host]:$port, PF $pfamily");
+      $sock = IO::Socket::INET->new();  # inet socket (IPv4 only)
+    }
+
+    if ($sock) {
+      ### create the handle under this package
+      bless $sock, $class;
+
+      $sock->NS_host($host);
+      $sock->NS_port($port);
+      $sock->NS_proto('SSL');
+      $sock->NS_family($pfamily);  # socket protocol family
+
+      for my $key (@ssl_args) {
+        my $val = defined($prop->{$key}) ? $prop->{$key} : $server->can($key) ? $server->$key($host, $port, 'SSL') : undef;
+        $sock->$key($val);
+      }
+      push @sockets_list, $sock;
+    }
   }
 
-  return $sock;
+  ### returns any number of sockets,
+  ### one for each protocol family (PF_INET or PF_INET6) and each bind address
+  return !wantarray ? $sockets_list[0] : @sockets_list;
 }
 
 sub log_connect {
   my $sock = shift;
-  my $server = shift;
-  my $host   = $sock->NS_host;
-  my $port   = $sock->NS_port;
-  my $proto  = $sock->NS_proto;
- $server->log(2,"Binding to $proto port $port on host $host\n");
+  my $server  = shift;
+  my $host    = $sock->NS_host; 
+  my $port    = $sock->NS_port;
+  my $proto   = $sock->NS_proto;
+  my $pfamily = $sock->NS_family || 0;
+  $server->log(2,"Binding to $proto port $port on host $host, PF $pfamily\n");
 }
 
-### connect the first time
+### bind the first time
 sub connect {
-  my $sock   = shift;
-  my $server = shift;
-  my $prop   = $server->{server};
-
-  my $host  = $sock->NS_host;
-  my $port  = $sock->NS_port;
-
-  my %args = ();
-  $args{LocalPort} = $port;                  # what port to bind on
-  $args{Proto}     = 'tcp';                  # what procol to use
-  $args{LocalAddr} = $host if $host !~ /\*/; # what local address (* is all)
-  $args{Listen}    = $prop->{listen};        # how many connections for kernel to queue
-  $args{Reuse}     = 1;  # allow us to rebind the port on a restart
-
-  ### add in any ssl specific properties
-  foreach ( keys %$prop ){
-    next unless /^SSL_/;
-    $args{$_} = $prop->{$_};
-  }
-
-  ### connect to the sock
-  $sock->SUPER::configure(\%args)
-    or $server->fatal("Can't connect to SSL port $port on $host [$!]");
-
-  $server->fatal("Back sock [$!]!".caller())
-    unless $sock;
+  my $sock    = shift;
+  my $server  = shift;
+  my $prop    = $server->{server};
+
+  my $host    = $sock->NS_host;
+  my $port    = $sock->NS_port;
+  my $pfamily = $sock->NS_family || 0;
 
+  my %args;
+  $args{LocalPort} = $port;
+  $args{Proto}     = 'tcp';
+  $args{LocalAddr} = $host if $host !~ /\*/;  # * is all
+  $args{Domain}    = $pfamily  if $have_inet6 && $pfamily;
+  $args{Listen}    = $prop->{listen};
+  $args{Reuse}     = 1;
+
+  ### bind to the sock using the underlying IO Socket module
+  { local @ISA = ( $io_socket_module );
+    $sock->SUPER::configure(\%args)
+      or $server->fatal("Can't bind to SSL port $port on $host [$!]");
+    $server->fatal("Bad sock [$!]!".caller())  if !$sock;
+  }
 }
 
 ### connect on a sig -HUP
 sub reconnect {
-  my $sock = shift;
-  my $fd   = shift;
-  my $server = shift;
-
-  $sock->fdopen( $fd, 'w' )
-    or $server->fatal("Error opening to file descriptor ($fd) [$!]");
+  my ($sock, $fd, $server) = @_;
 
+  my $host    = $sock->NS_host; 
+  my $port    = $sock->NS_port;
+  my $proto   = $sock->NS_proto;
+  my $pfamily = $sock->NS_family || 0;
+
+  $server->log(3,"Reassociating file descriptor $fd ".
+                 "with socket $proto on [$host]:port, PF $pfamily\n");
+
+  ### fdopen cannot be used on a IO::Socket::SSL object!!!
+  ### use fdopen() from the underlying IO Socket package
+  { local @ISA = ( $io_socket_module );
+    $sock->fdopen( $fd, 'w' )
+      or $server->fatal("Error opening to file descriptor ($fd) [$!]");
+  }
 }
 
 ### allow for endowing the child
 sub accept {
   my $sock = shift;
-  my $client = $sock->SUPER::accept();
+  my $client;
 
-  ### pass items on
-  if( defined($client) ){
-    bless $client, ref($sock);
-    $client->NS_proto( $sock->NS_proto );
+  ### fdopen (in reconnect) cannot be used on an IO::Socket::SSL object,
+  ### which is why we accept first and upgrade to SSL later
+
+  ### accept() with the underlying IO Socket package, upgrade to SSL later
+  { local @ISA = ( $io_socket_module );
+    $client = $sock->SUPER::accept();
   }
 
+  if( defined $client ){
+    $client->NS_proto( $sock->NS_proto );
+    $client->NS_family( $sock->NS_family );
+    $client->NS_host( $sock->NS_host );
+    $client->NS_port( $sock->NS_port );
+
+    ### must bless the upgraded SSL object into our package
+    ### to be able to reference its NS_* properties later
+    __PACKAGE__->start_SSL($client,
+      SSL_error_trap => sub { my($sock,$msg) = @_;
+                              die "Error upgrading socket to SSL: $msg" },
+      SSL_server => 1,
+      map { defined $sock->$_() ? ($_,$sock->$_()) : () } @ssl_args,
+    ) or die "Upgrading socket to SSL failed: ".IO::Socket::SSL::errstr();
+
+  }
   return $client;
 }
 
@@ -157,6 +264,7 @@
               $sock->NS_host,
               $sock->NS_port,
               $sock->NS_proto,
+              !$have_inet6 || !$sock->NS_family ? () : $sock->NS_family,
               );
 }
 
@@ -164,7 +272,7 @@
 sub show {
   my $sock = shift;
   my $t = "Ref = \"" .ref($sock) . "\"\n";
-  foreach my $prop ( qw(NS_proto NS_port NS_host) ){
+  foreach my $prop ( qw(NS_proto NS_port NS_host NS_family) ){
     $t .= "  $prop = \"" .$sock->$prop()."\"\n";
   }
   return $t;
@@ -179,7 +287,7 @@
     die "No property called.";
   }
 
-  if( $prop =~ /^(NS_proto|NS_port|NS_host)$/ ){
+  if( $prop =~ /^(NS_proto|NS_port|NS_host|NS_family|SSL_\w+)$/ ){
     no strict 'refs';
     * { __PACKAGE__ ."::". $prop } = sub {
       my $sock = shift;
@@ -215,8 +323,8 @@
 =head1 DESCRIPTION
 
 This original SSL module was experimental.  It has been superceeded by
-Net::Server::Proto::SSLEAY If anybody has any successes or ideas for
-improvment under SSL, please email <paul@seamons.com>.
+Net::Server::Proto::SSLEAY. If anybody has any successes or ideas for
+improvement under SSL, please email <paul@seamons.com>.
 
 Protocol module for Net::Server.  This module implements a
 secure socket layer over tcp (also known as SSL).
--- Net-Server-0.99/lib/Net/Server/Proto/TCP.pm.orig	2011-08-01 10:24:36.463625993 -0700
+++ lib/Net/Server/Proto/TCP.pm	2011-08-01 11:08:27.283623011 -0700
@@ -22,11 +22,22 @@
 package Net::Server::Proto::TCP;
 
 use strict;
-use vars qw($VERSION $AUTOLOAD @ISA);
-use IO::Socket ();
+use vars qw($VERSION $AUTOLOAD @ISA $have_inet6);
+use IO::Socket;
+
+BEGIN {
+  eval {
+    require Socket6; import Socket6;
+    require IO::Socket::INET6;
+    @ISA = qw(IO::Socket::INET6);
+    $have_inet6 = 1;
+  } or do {
+    require IO::Socket::INET;
+    @ISA = qw(IO::Socket::INET);
+  };
+}
 
 $VERSION = $Net::Server::VERSION; # done until separated
-@ISA = qw(IO::Socket::INET);
 
 sub object {
   my $type  = shift;
@@ -35,11 +46,16 @@
   my ($default_host,$port,$server) = @_;
   my $host;
 
-  ### allow for things like "domain.com:80"
-  if( $port =~ m/^([\w\.\-\*\/]+):(\w+)$/ ){
+  local($1,$2);
+  ### allow for things like "[::1]:80" or "[host.example.com]:80"
+  if( $port =~ m/^\[([^\]]*)\]:(\w+)$/ ){
     ($host,$port) = ($1,$2);
 
-  ### allow for things like "80"
+  ### allow for things like "host.example.com:80"
+  }elsif( $port =~ m/^([\w\.\-\*\/]+):(\w+)$/ ){
+    ($host,$port) = ($1,$2);
+
+  ### allow for things like "80" or "http"
   }elsif( $port =~ /^(\w+)$/ ){
     ($host,$port) = ($default_host,$1);
 
@@ -48,65 +64,137 @@
     $server->fatal("Undeterminate port \"$port\" under ".__PACKAGE__);
   }
 
-  ### create the handle under this package
-  my $sock = $class->SUPER::new();
+  ### collect bind addresses along with their address family for all hosts
+  my @bind_tuples;
+  if( $host =~ /^\d{1,3}(?:\.\d{1,3}){3}\z/ ){
+    push(@bind_tuples, [AF_INET,$host,$port]);
+  }elsif( $host =~ /:/ ){
+    die "No IO::Socket::INET6, cannot bind to [$host]:$port"  if !$have_inet6;
+    push(@bind_tuples, [AF_INET6,$host,$port]);
+  }elsif( !$have_inet6 ){
+    push(@bind_tuples, [AF_INET,$host,$port]);
+  }elsif( $have_inet6 && $host =~ /\*/ ){
+    push(@bind_tuples, [AF_INET6,$host,$port], [AF_INET,$host,$port]);
+  }else{  # we do have IO::Socket::INET6, it handles inet6 as well as inet
+    # obtain a list of IP addresses for $host, resolve port name
+    my @res1 = getaddrinfo($host, $port, AF_UNSPEC, SOCK_STREAM, 0,
+                           AI_PASSIVE|AI_ADDRCONFIG);
+    die "Unresolvable [$host]:$port: $res1[0]"  if @res1 < 5;
+    while (@res1 >= 5) {
+      my($afam, $socktype, $proto, $saddr, $canonname);
+      ($afam, $socktype, $proto, $saddr, $canonname, @res1) = @res1;
+      my @res2 = getnameinfo($saddr, NI_NUMERICHOST | NI_NUMERICSERV);
+      die "getnameinfo failed on [$host]:$port: $res2[0]"  if @res2 < 2;
+      my($hostip,$portnum) = @res2;
+      $server->log(4,"Resolved [$host]:$port -> [$hostip]:$portnum, AF $afam");
+      push(@bind_tuples, [$afam,$hostip,$portnum]);
+    }
+  }
 
-  ### store some properties
-  $sock->NS_host($host);
-  $sock->NS_port($port);
-  $sock->NS_proto('TCP');
+  my @sockets_list;
+  ### create a socket for each specified bind address and family
+  foreach my $tuple ( @bind_tuples ){
+    my $afamily;  # address family (AF_* constants)
+    my $pfamily;  # socket protocol family (PF_* constants)
+    ($afamily,$host,$port) = @$tuple;
+    my $sock;
+    if( $have_inet6 ){
+      # Using IO::Socket::INET6 to handle both the IPv4 and IPv6.
+      # Constants PF_INET/PF_INET6 (protocol family) usually happen to have
+      # the same value as AF_INET/AF_INET6 (address family) constants.
+      # Still, better safe than sorry:
+      if ( $afamily == AF_INET ) {
+        $pfamily = PF_INET;
+      } elsif ( $afamily == AF_INET6 ) {
+        $pfamily = PF_INET6;
+      } else {
+        $pfamily = $afamily;
+      }
+      $server->log(3,"Using IO::Socket::INET6 for [$host]:$port, PF $pfamily");
+      $sock = IO::Socket::INET6->new(Domain => $pfamily);  # inet or inet6
+    }else{
+      $pfamily = PF_INET;
+      $server->log(3,"Using IO::Socket::INET for [$host]:$port, PF $pfamily");
+      $sock = IO::Socket::INET->new();  # inet socket (IPv4 only)
+    }
 
-  return $sock;
+    if ($sock) {
+      ### create the handle under this package
+      bless $sock, $class;
+
+      ### store some properties
+      $sock->NS_host($host);
+      $sock->NS_port($port);
+      $sock->NS_proto('TCP');
+      $sock->NS_family($pfamily);  # socket protocol family
+      push @sockets_list, $sock;
+    }
+  }
+
+  ### returns any number of sockets,
+  ### one for each protocol family (PF_INET or PF_INET6) and each bind address
+  return !wantarray ? $sockets_list[0] : @sockets_list;
 }
 
 sub log_connect {
   my $sock = shift;
-  my $server = shift;
-  my $host   = $sock->NS_host; 
-  my $port   = $sock->NS_port;
-  my $proto  = $sock->NS_proto;
- $server->log(2,"Binding to $proto port $port on host $host\n");
+  my $server  = shift;
+  my $host    = $sock->NS_host; 
+  my $port    = $sock->NS_port;
+  my $proto   = $sock->NS_proto;
+  my $pfamily = $sock->NS_family || 0;
+  $server->log(2,"Binding to $proto port $port on host $host, PF $pfamily\n");
 }
 
-### connect the first time
+### bind the first time
 sub connect {
-  my $sock   = shift;
-  my $server = shift;
-  my $prop   = $server->{server};
+  my $sock    = shift;
+  my $server  = shift;
+  my $prop    = $server->{server};
+
+  my $host    = $sock->NS_host;
+  my $port    = $sock->NS_port;
+  my $pfamily = $sock->NS_family || 0;
 
-  my $host  = $sock->NS_host;
-  my $port  = $sock->NS_port;
-
-  my %args = ();
+  my %args;
   $args{LocalPort} = $port;                  # what port to bind on
   $args{Proto}     = 'tcp';                  # what procol to use
   $args{LocalAddr} = $host if $host !~ /\*/; # what local address (* is all)
+  $args{Domain}    = $pfamily  if $have_inet6 && $pfamily;
   $args{Listen}    = $prop->{listen};        # how many connections for kernel to queue
   $args{Reuse}     = 1;  # allow us to rebind the port on a restart
 
-  ### connect to the sock
+  ### bind the sock
   $sock->SUPER::configure(\%args)
-    or $server->fatal("Can't connect to TCP port $port on $host [$!]");
+    or $server->fatal("Can't bind to TCP port $port on $host [$!]");
+  $server->fatal("Bad sock [$!]!".caller())  if !$sock;
 
-  if ($port == 0 && ($port = $sock->sockport)) {
-    $sock->NS_port($port);
-    $server->log(2,"Bound to auto-assigned port $port");
+  my $actual_port = $sock->sockport;
+  # $port may be a service name, compare as strings
+  if( $actual_port && (!defined $port || $actual_port ne $port) ){
+    $sock->NS_port($actual_port);
+    if( $port =~ /^0*\z/ ){
+      $server->log(2,"Bound to auto-assigned port $actual_port");
+    }else{
+      $server->log(3,"Bound to service \"$port\", port number $actual_port");
+    }
   }
 
-  $server->fatal("Back sock [$!]!".caller())
-    unless $sock;
-
 }
 
-### connect on a sig -HUP
+### reassociate sockets with inherited file descriptors on a sig -HUP
 sub reconnect {
-  my $sock = shift;
-  my $fd   = shift;
-  my $server = shift;
+  my ($sock, $fd, $server) = @_;
 
+  my $host    = $sock->NS_host; 
+  my $port    = $sock->NS_port;
+  my $proto   = $sock->NS_proto;
+  my $pfamily = $sock->NS_family || 0;
+
+  $server->log(3,"Reassociating file descriptor $fd ".
+                 "with socket $proto on [$host]:port, PF $pfamily\n");
   $sock->fdopen( $fd, 'w' )
     or $server->fatal("Error opening to file descriptor ($fd) [$!]");
-
 }
 
 ### allow for endowing the child
@@ -115,8 +203,11 @@
   my $client = $sock->SUPER::accept();
 
   ### pass items on
-  if( defined($client) ){
+  if( defined $client ){
     $client->NS_proto( $sock->NS_proto );
+    $client->NS_family( $sock->NS_family );
+    $client->NS_host( $sock->NS_host );
+    $client->NS_port( $sock->NS_port );
   }
 
   return $client;
@@ -156,6 +247,7 @@
               $sock->NS_host,
               $sock->NS_port,
               $sock->NS_proto,
+              !$have_inet6 || !$sock->NS_family ? () : $sock->NS_family,
               );
 }
 
@@ -163,7 +255,7 @@
 sub show {
   my $sock = shift;
   my $t = "Ref = \"" .ref($sock) . "\"\n";
-  foreach my $prop ( qw(NS_proto NS_port NS_host) ){
+  foreach my $prop ( qw(NS_proto NS_port NS_host NS_family) ){
     $t .= "  $prop = \"" .$sock->$prop()."\"\n";
   }
   return $t;
@@ -178,7 +270,7 @@
     die "No property called.";
   }
 
-  if( $prop =~ /^(NS_proto|NS_port|NS_host|NS_recv_len|NS_recv_flags)$/ ){
+  if( $prop =~ /^(NS_proto|NS_port|NS_host|NS_family|NS_recv_len|NS_recv_flags)$/ ){
     no strict 'refs';
     * { __PACKAGE__ ."::". $prop } = sub {
       my $sock = shift;
