# -*- perl -*-
#
# Net::Server::Proto::UNIX - Net::Server Protocol module
#
# $Id: UNIX.pm,v 1.11 2007/02/03 05:56:22 rhandom Exp $
#
# Copyright (C) 2001-2007
#
# Paul Seamons
# paul@seamons.com
# http://seamons.com/
#
# This package may be distributed under the terms of either the
# GNU General Public License
# or the
# Perl Artistic License
#
# All rights reserved.
#
################################################################
package Net::Server::Proto::UNIX;
use strict;
use vars qw($VERSION $AUTOLOAD @ISA);
use IO::Socket ();
use Socket qw(SOCK_STREAM SOCK_DGRAM);
$VERSION = $Net::Server::VERSION; # done until separated
@ISA = qw(IO::Socket::UNIX);
sub object {
my $type = shift;
my $class = ref($type) || $type || __PACKAGE__;
my ($default_host,$port,$server) = @_;
my $prop = $server->{server};
### read any additional protocol specific arguments
$server->configure({
unix_type => \$prop->{unix_type},
unix_path => \$prop->{unix_path},
});
my $u_type = $prop->{unix_type} || SOCK_STREAM;
my $u_path = $prop->{unix_path} || undef;
### allow for things like "/tmp/myfile.sock|SOCK_STREAM"
if( $port =~ m/^([\w\.\-\*\/]+)\|(\w+)$/ ){
($u_path,$u_type) = ($1,$2);
### allow for things like "/tmp/myfile.sock"
}elsif( $port =~ /^([\w\.\-\*\/]+)$/ ){
$u_path = $1;
### don't know that style of port
}else{
$server->fatal("Undeterminate port \"$port\" under ".__PACKAGE__);
}
### allow for the string rather than the function
if( $u_type eq 'SOCK_STREAM' ){
$u_type = SOCK_STREAM;
}elsif( $u_type eq 'SOCK_DGRAM' ){
$u_type = SOCK_DGRAM;
}
### create a blank socket
my $sock = $class->SUPER::new();
### set a few more parameters for SOCK_DGRAM
if( $u_type == SOCK_DGRAM ){
$prop->{udp_recv_len} = 4096
unless defined($prop->{udp_recv_len})
&& $prop->{udp_recv_len} =~ /^\d+$/;
$prop->{udp_recv_flags} = 0
unless defined($prop->{udp_recv_flags})
&& $prop->{udp_recv_flags} =~ /^\d+$/;
$sock->NS_recv_len( $prop->{udp_recv_len} );
$sock->NS_recv_flags( $prop->{udp_recv_flags} );
}elsif( $u_type == SOCK_STREAM ){
}else{
$server->fatal("Invalid type for UNIX socket ($u_type)... must be SOCK_STREAM or SOCK_DGRAM");
}
### set some common parameters
$sock->NS_unix_type( $u_type );
$sock->NS_unix_path( $u_path );
$sock->NS_proto('UNIX');
return $sock;
}
sub log_connect {
my $sock = shift;
my $server = shift;
my $unix_path = $sock->NS_unix_path;
my $type = ($sock->NS_unix_type == SOCK_STREAM) ? 'SOCK_STREAM' : 'SOCK_DGRAM';
$server->log(2,"Binding to UNIX socket file $unix_path using $type\n");
}
### connect 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 $unix_path = $sock->NS_unix_path;
my $unix_type = $sock->NS_unix_type;
my %args = ();
$args{Local} = $unix_path; # what socket file to bind to
$args{Type} = $unix_type; # SOCK_STREAM (default) or SOCK_DGRAM
if( $unix_type != SOCK_DGRAM ){
$args{Listen} = $prop->{listen}; # how many connections for kernel to queue
}
### remove the old socket if it is still there
if( -e $unix_path && ! unlink($unix_path) ){
$server->fatal("Can't connect to UNIX socket at file $unix_path [$!]");
}
### connect to the sock
$sock->SUPER::configure(\%args)
or $server->fatal("Can't connect to UNIX socket at file $unix_path [$!]");
$server->fatal("Back sock [$!]!".caller())
unless $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) [$!]");
}
### allow for endowing the child
sub accept {
my $sock = shift;
my $client = $sock->SUPER::accept();
### pass items on
if( defined($client) ){
$client->NS_proto( $sock->NS_proto );
$client->NS_unix_path( $sock->NS_unix_path );
$client->NS_unix_type( $sock->NS_unix_type );
}
return $client;
}
### a string containing any information necessary for restarting the server
### via a -HUP signal
### a newline is not allowed
### the hup_string must be a unique identifier based on configuration info
sub hup_string {
my $sock = shift;
return join("|",
$sock->NS_unix_path,
$sock->NS_unix_type,
$sock->NS_proto,
);
}
### short routine to show what we think we are
sub show {
my $sock = shift;
my $t = "Ref = \"" .ref($sock) . "\"\n";
foreach my $prop ( qw(NS_proto NS_unix_path NS_unix_type) ){
$t .= " $prop = \"" .$sock->$prop()."\"\n";
}
$t =~ s/"1"/SOCK_STREAM/;
$t =~ s/"2"/SOCK_DGRAM/;
return $t;
}
### self installer
sub AUTOLOAD {
my $sock = shift;
my ($prop) = $AUTOLOAD =~ /::([^:]+)$/ ? $1 : '';
if( ! $prop ){
die "No property called.";
}
if( $prop =~ /^(NS_proto|NS_unix_path|NS_unix_type|NS_recv_len|NS_recv_flags)$/ ){
no strict 'refs';
* { __PACKAGE__ ."::". $prop } = sub {
my $sock = shift;
if( @_ ){
${*$sock}{$prop} = shift;
delete ${*$sock}{$prop} unless defined ${*$sock}{$prop};
}else{
return ${*$sock}{$prop};
}
};
use strict 'refs';
$sock->$prop(@_);
}else{
die "What method is that? [$prop]";
}
}
1;
__END__
=head1 NAME
Net::Server::Proto::UNIX - adp0 - Net::Server UNIX protocol.
=head1 SYNOPSIS
See L<Net::Server::Proto>.
=head1 DESCRIPTION
Protocol module for Net::Server. This module implements the
SOCK_DGRAM and SOCK_STREAM socket types under UNIX.
See L<Net::Server::Proto>.
Any sockets created during startup will be chown'ed to the
user and group specified in the starup arguments.
=head1 PARAMETERS
The following paramaters may be specified in addition to
normal command line parameters for a Net::Server. See
L<Net::Server> for more information on reading arguments.
=over 4
=item unix_type
Can be either SOCK_STREAM or SOCK_DGRAM (default is SOCK_STREAM).
This can also be passed on the port line (see L<Net::Server::Proto>).
=item unix_path
Default path to the socket file for this UNIX socket. Default
is undef. This can also be passed on the port line (see
L<Net::Server::Proto>).
=back
=head1 QUICK PARAMETER LIST
Key Value Default
## UNIX socket parameters
unix_type (SOCK_STREAM|SOCK_DGRAM) SOCK_STREAM
unix_path "filename" undef
=head1 LICENCE
Distributed under the same terms as Net::Server
=cut
syntax highlighted by Code2HTML, v. 0.9.1