]> Sergey Matveev's repositories - public-inbox.git/commitdiff
daemon: introduce host_with_port for identifying sockets
authorEric Wong <e@80x24.org>
Thu, 3 Mar 2016 05:14:31 +0000 (05:14 +0000)
committerEric Wong <e@80x24.org>
Thu, 3 Mar 2016 09:19:16 +0000 (09:19 +0000)
This allows us to share more code between daemons and avoids
having to make additional syscalls for preparing REMOTE_HOST
and REMOTE_PORT in the PSGI env in -httpd.

This will also make supporting HTTP (and NNTP) over Unix sockets
easier in a future commit.

lib/PublicInbox/Daemon.pm
lib/PublicInbox/HTTP.pm
script/public-inbox-httpd
t/httpd-corner.psgi
t/httpd-corner.t

index 77ab2a71c166ba39b7844c8186baeec3bf1530ab..c101ecb7ad538313324879c4986587ca30fee0d8 100644 (file)
@@ -157,20 +157,23 @@ sub reopen_logs {
 
 sub sockname ($) {
        my ($s) = @_;
-       my $n = getsockname($s) or return;
-       my ($port, $addr);
-       if (length($n) >= 28) {
+       my $addr = getsockname($s) or return;
+       my ($host, $port) = host_with_port($addr);
+       "$host:$port";
+}
+
+sub host_with_port ($) {
+       my ($addr) = @_;
+       my ($port, $host);
+       if (length($addr) >= 28) {
                require Socket6;
-               ($port, $addr) = Socket6::unpack_sockaddr_in6($n);
-       } else {
-               ($port, $addr) = Socket::sockaddr_in($n);
-       }
-       if (length($addr) == 4) {
-               $n = Socket::inet_ntoa($addr)
+               ($port, $host) = Socket6::unpack_sockaddr_in6($addr);
+               $host = '['.Socket6::inet_ntop(Socket6::AF_INET6(), $host).']';
        } else {
-               $n = '['.Socket6::inet_ntop(Socket6::AF_INET6(), $addr).']';
+               ($port, $host) = Socket::sockaddr_in($addr);
+               $host = Socket::inet_ntoa($host);
        }
-       $n .= ":$port";
+       ($host, $port);
 }
 
 sub inherit () {
index 17e7447545ca145a262bc055d60c338dcbcf050a..6c4c20d7cf801663af01beb71d3676bc941c6479 100644 (file)
@@ -11,7 +11,7 @@ package PublicInbox::HTTP;
 use strict;
 use warnings;
 use base qw(Danga::Socket);
-use fields qw(httpd env rbuf input_left);
+use fields qw(httpd env rbuf input_left remote_addr remote_port);
 use Fcntl qw(:seek);
 use HTTP::Parser::XS qw(parse_http_request); # supports pure Perl fallback
 use HTTP::Status qw(status_message);
@@ -38,6 +38,8 @@ sub new ($$$) {
        $self->SUPER::new($sock);
        $self->{httpd} = $httpd;
        $self->{rbuf} = '';
+       ($self->{remote_addr}, $self->{remote_port}) =
+               PublicInbox::Daemon::host_with_port($addr);
        $self->watch_read(1);
        $self;
 }
@@ -113,8 +115,8 @@ sub app_dispatch ($) {
        my ($self) = @_;
        $self->watch_read(0);
        my $env = $self->{env};
-       $env->{REMOTE_ADDR} = $self->peer_ip_string; # Danga::Socket
-       $env->{REMOTE_PORT} = $self->{peer_port}; # set by peer_ip_string
+       $env->{REMOTE_ADDR} = $self->{remote_addr};
+       $env->{REMOTE_PORT} = $self->{remote_port};
        if (my $host = $env->{HTTP_HOST}) {
                $host =~ s/:(\d+)\z// and $env->{SERVER_PORT} = $1;
                $env->{SERVER_NAME} = $host;
index d867b47718e764454b6472c7dcd8311b9ccae37d..b6c4e6777c3fb73a1393a1a228676d5331d00a93 100755 (executable)
@@ -99,18 +99,10 @@ sub pi_httpd_async {
 sub new {
        my ($class, $sock, $app) = @_;
        my $n = getsockname($sock) or die "not a socket: $sock $!\n";
-       my ($port, $addr);
-       if (length($n) >= 28) {
-               require Socket6;
-               ($port, $addr) = Socket6::unpack_sockaddr_in6($n);
-       } else {
-               ($port, $addr) = Socket::unpack_sockaddr_in($n);
-       }
+       my ($host, $port) = PublicInbox::Daemon::host_with_port($n);
 
        my %env = (
-               REMOTE_HOST => '',
-               REMOTE_PORT => 0,
-               SERVER_NAME => $addr,
+               SERVER_NAME => $host,
                SERVER_PORT => $port,
                SCRIPT_NAME => '',
                'psgi.version' => [ 1, 1 ],
index c3bf5231e209c9bc98edea0316183eefc9f58886..349b35dfb22d32df1096af54cba0f4001b19f7b0 100644 (file)
@@ -44,6 +44,9 @@ my $app = sub {
                                $fh->close;
                        };
                }
+       } elsif ($path eq '/host-port') {
+               $code = 200;
+               push @$body, "$env->{REMOTE_ADDR}:$env->{REMOTE_PORT}";
        }
 
        [ $code, $h, $body ]
index e73ebd5e05ec3473330008682760ca6d052d853a..198a7e90e7345398480f77cd1ae4f5367ac60008 100644 (file)
@@ -76,6 +76,16 @@ sub conn_for {
        return $conn;
 }
 
+{
+       my $conn = conn_for($sock, 'host-port');
+       $conn->write("GET /host-port HTTP/1.0\r\n\r\n");
+       $conn->read(my $buf, 4096);
+       my ($head, $body) = split(/\r\n\r\n/, $buf);
+       my ($addr, $port) = split(/:/, $body);
+       is($addr, $conn->sockhost, 'host matches addr');
+       is($port, $conn->sockport, 'port matches');
+}
+
 # graceful termination
 {
        my $conn = conn_for($sock, 'graceful termination via slow header');