@@ -64,6 +64,7 @@ sub new {
6464 read_size => 4096,
6565 max_header_size => MAX_READ_SIZE, # 4096*8,
6666 request => ' AnyEvent::HTTP::Server::Req' ,
67+ sockets => {},
6768 @_ ,
6869 }, $pkg ;
6970
@@ -126,48 +127,59 @@ sub listen:method {
126127 my $self = shift ;
127128
128129 for my $listen (@{ $self -> {listen } }) {
129- my ($host ,$service ) = split ' :' ,$listen ,2;
130- $service = $self -> {port } unless length $service ;
131- $host = $self -> {host } unless length $host ;
132- $host = $AnyEvent::PROTOCOL {ipv4 } < $AnyEvent::PROTOCOL {ipv6 } && AF_INET6 ? " ::" : " 0" unless length $host ;
133-
134- my $ipn = parse_address $host
135- or Carp::croak " $self .listen: cannot parse '$host ' as host address" ;
136-
137- my $af = address_family $ipn ;
138-
139- # win32 perl is too stupid to get this right :/
140- Carp::croak " listen/socket: address family not supported"
141- if AnyEvent::WIN32 && $af == AF_UNIX;
142-
143- socket my $fh , $af , SOCK_STREAM, 0 or Carp::croak " listen/socket: $! " ;
144-
145- if ($af == AF_INET || $af == AF_INET6) {
146- setsockopt $fh , SOL_SOCKET, SO_REUSEADDR, 1
147- or Carp::croak " listen/so_reuseaddr: $! "
148- unless AnyEvent::WIN32; # work around windows bug
130+ my $fh ;
131+ unless ($self -> {sockets }-> {$listen }) {
132+ my ($host ,$service ) = split ' :' ,$listen ,2;
133+ $service = $self -> {port } unless length $service ;
134+ $host = $self -> {host } unless length $host ;
135+ $host = $AnyEvent::PROTOCOL {ipv4 } < $AnyEvent::PROTOCOL {ipv6 } && AF_INET6 ? " ::" : " 0" unless length $host ;
149136
150- unless ($service =~ / ^\d *$ / ) {
151- $service = (getservbyname $service , " tcp" )[2]
152- or Carp::croak " tcp_listen: $service : service unknown"
137+ my $ipn = parse_address $host
138+ or Carp::croak " $self .listen: cannot parse '$host ' as host address" ;
139+
140+ my $af = address_family $ipn ;
141+
142+ # win32 perl is too stupid to get this right :/
143+ Carp::croak " listen/socket: address family not supported"
144+ if AnyEvent::WIN32 && $af == AF_UNIX;
145+
146+ socket $fh , $af , SOCK_STREAM, 0 or Carp::croak " listen/socket: $! " ;
147+
148+ if ($af == AF_INET || $af == AF_INET6) {
149+ setsockopt $fh , SOL_SOCKET, SO_REUSEADDR, 1
150+ or Carp::croak " listen/so_reuseaddr: $! "
151+ unless AnyEvent::WIN32; # work around windows bug
152+
153+ unless ($service =~ / ^\d *$ / ) {
154+ $service = (getservbyname $service , " tcp" )[2]
155+ or Carp::croak " tcp_listen: $service : service unknown"
156+ }
157+ } elsif ($af == AF_UNIX) {
158+ unlink $service ;
153159 }
154- } elsif ( $af == AF_UNIX) {
155- unlink $ service;
156- }
157-
158- bind $fh , AnyEvent::Socket::pack_sockaddr( $service , $ipn )
159- or Carp::croak " listen/bind on " . eval {Socket::inet_ntoa( $ipn )}. " : $service : $! " ;
160-
161- if ( $host eq ' unix/ ' ) {
162- chmod oct ( ' 0777 ' ), $service
163- or warn " chmod $service failed: $! " ;
160+
161+ bind $fh , AnyEvent::Socket::pack_sockaddr( $ service, $ipn )
162+ or Carp::croak " listen/bind on " . eval {Socket::inet_ntoa( $ipn )}. " : $service : $! " ;
163+
164+ if ( $host eq ' unix/ ' ) {
165+ chmod oct ( ' 0777 ' ), $service
166+ or warn " chmod $service failed: $! " ;
167+ }
168+ } else {
169+ $fh = delete $self -> { sockets } -> { $listen } ;
164170 }
165171
166172 fh_nonblocking $fh , 1;
167173
168174 $self -> {fh } ||= $fh ; # compat
169175 $self -> {fhs }{fileno $fh } = $fh ;
176+ $self -> {fhs_named }{$listen } = $fh ;
177+ }
178+
179+ for my $socket (values $self -> {sockets }) {
180+ close $socket ;
170181 }
182+ $self -> {sockets } = {};
171183
172184 $self -> prepare();
173185
0 commit comments