### UNIX.pm  -*- Perl -*-
## Unix domain socket support for HTTP::Server::Simple.

### Ivan Shmakov, 2022

## To the extent possible under law, the author(s) have dedicated
## all copyright and related and neighboring rights to this software
## to the public domain worldwide.  This software is distributed
## without any warranty.

## You should have received a copy of the CC0 Public Domain Dedication
## along with this software.  If not, see
## <http://creativecommons.org/publicdomain/zero/1.0/>.

## Alternatively, at your option, you can redistribute this library
## and (or) modify it under the same terms as Perl itself.

### History:

## 0.2  2022-12-07 12:24Z
##      ($VERSION): Updated.
##      (HTTP::Server::Simple::UNIX::Selftest): Fixed: split the
##      test suite into a separate file (was: part of the file and
##      enabled unconditionally, thus preventing normal module use.)

## 0.1  2022-12-07 11:05:36Z
##      (sfn.s3vkjxwW96ZjdOPX-Uzp-i22EabwJNorlwJbt8mrIiQ.pm)
##      Initial revision.

### Code:
package HTTP::Server::Simple::UNIX;

use common::sense;

require HTTP::Server::Simple;
require Socket;

our $VERSION = "0.2";

our @ISA = qw (HTTP::Server::Simple);

sub unix_socket_name
{
    $_[0]->{"unixname"} = $_[1]
        if (1 < @_);
    ## .
    $_[0]->{"unixname"};
}

sub setup_listener
{
    my ($self) = @_;

    my $un
        = $self->unix_socket_name ();
    ## .
    return SUPER->setup_listener ()
        unless (defined ($un));

    my $ad
        = Socket::sockaddr_un ($un);
    ## FIXME: HTTP::Server::Simple is ought to have a hook for this
    package HTTP::Server::Simple;
    my $so
        = socket (HTTPDaemon,
                  Socket::PF_UNIX (), Socket::SOCK_STREAM (), 0)
        or die ("socket: ", $!);
    bind (HTTPDaemon, $ad)
        or die ("bind: ", $!);
    ## .
    listen (HTTPDaemon, 3)
        or die ("listen: ", $!);
}

## FIXME: HTTP::Server::Simple::_process_request should call a hook,
##        instead of calling sockaddr_in directly
*unpack_sockaddr_in_saved
    = \&Socket::unpack_sockaddr_in;
sub unpack_sockaddr_in_guarded
{
    my $r
        = eval { unpack_sockaddr_in_saved (@_); };
    my $s
        = $@;
    ## .
    return $r
        if ("" eq $s);
    ## FIXME: should perhaps look in callstack and try _un iff
    ##        called from HTTP::Server::Simple ?
    my $q
        = eval { Socket::unpack_sockaddr_un (@_); };
    die ("Called on neither INET nor UNIX address: ", $s, ", ", $@)
        unless ("" eq $@);
    ## .
    return undef;
}
*Socket::unpack_sockaddr_in
    = \&unpack_sockaddr_in_guarded;

## .
1;

### UNIX.pm ends here
