package Guardian::Socket; use strict; use warnings; use Exporter qw(import); our @EXPORT_OK = qw(Server Client Message_Parser); use IO::Socket::UNIX qw( SOCK_STREAM SOMAXCONN ); # The path and filename to the UNIX socket. my $socketpath = "/run/guardian"; my $socketfile = "/run/guardian/guardian.sock"; # Hash with all supported socket commands and events which should # be returned by the parser. my %supported_commands = ( 'block' => 'block', 'unblock' => 'unblock', 'flush' => 'flush', 'reload' => 'reload', 'logrotate' => 'logrotate', ); # ## Socket server function. # ## It is used to create the server component to provide an IPC ## mechanism for guardian. The server function creates an UNIX ## socket. # sub Server () { # If the path for the socketfile does not exist, try to # create it. unless (-d "$socketpath") { mkdir("$socketpath") or die "Could not create $socketpath: $@\n"; } # Delete an existing socket file. if (-e "$socketfile") { unlink $socketfile or die "Could not release existing socket file: $!\n"; } # Create a new UNIX socket. my $server = IO::Socket::UNIX->new( Local => $socketfile, Listen => SOMAXCONN, Type => SOCK_STREAM, ) or die "Could not create socket: $@\n"; # Return the server object. return $server; } # ## A client for the socket server. # ## This function provides a simple client to connect to the server socket ## and send messages through it to a running guardian process. # sub Client($) { my ($message) = @_; # Create the client and connect to the server socket. my $client = IO::Socket::UNIX->new( Type => SOCK_STREAM, Peer => $socketfile, ) or die "Could not connect to socketfile: $!\n"; # Remove any newline. chomp($message); # Send the message through the socket. print $client "$message\n"; } # ## The Socket message parser. # ## This subfunction is responsible for parsing any data or messages ## which have been recieved through the server socket. # sub Message_Parser ($) { # Splitt the message into single parts. # The first part contains the command, the second # one an optional argument. my @message = split(/ /, $_[0]); my ($command, $optarg, $unsupported) = @message; # Currently only socket messages with two arguments (command and # the additional argument which is required for some commands) # are supported. If a third argument is passed, the message # is invalid and the parser returns false. if ($unsupported) { return undef; } # Check if we got a supported command. if (exists $supported_commands{$command}) { # Check an optional argument has been given. if ($optarg) { # The message is valid, return the event and # the optional argument. return "$supported_commands{$command} $optarg"; } else { # Only return the event for the recieved command. return "$supported_commands{$command}"; } } # If we got here, the command was not supported or something different # went wrong. In such cases the function will return undef (False). return undef; } 1;