From b38de6f02fa04e36b881d2aad9c7f792beb0b6a1 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Thu, 3 Mar 2016 05:14:31 +0000 Subject: daemon: introduce host_with_port for identifying sockets 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 | 25 ++++++++++++++----------- lib/PublicInbox/HTTP.pm | 8 +++++--- script/public-inbox-httpd | 12 ++---------- t/httpd-corner.psgi | 3 +++ t/httpd-corner.t | 10 ++++++++++ 5 files changed, 34 insertions(+), 24 deletions(-) diff --git a/lib/PublicInbox/Daemon.pm b/lib/PublicInbox/Daemon.pm index 77ab2a71..c101ecb7 100644 --- a/lib/PublicInbox/Daemon.pm +++ b/lib/PublicInbox/Daemon.pm @@ -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 () { diff --git a/lib/PublicInbox/HTTP.pm b/lib/PublicInbox/HTTP.pm index 17e74475..6c4c20d7 100644 --- a/lib/PublicInbox/HTTP.pm +++ b/lib/PublicInbox/HTTP.pm @@ -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; diff --git a/script/public-inbox-httpd b/script/public-inbox-httpd index d867b477..b6c4e677 100755 --- a/script/public-inbox-httpd +++ b/script/public-inbox-httpd @@ -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 ], diff --git a/t/httpd-corner.psgi b/t/httpd-corner.psgi index c3bf5231..349b35df 100644 --- a/t/httpd-corner.psgi +++ b/t/httpd-corner.psgi @@ -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 ] diff --git a/t/httpd-corner.t b/t/httpd-corner.t index e73ebd5e..198a7e90 100644 --- a/t/httpd-corner.t +++ b/t/httpd-corner.t @@ -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'); -- cgit v1.2.3-24-ge0c7