From 0b0ec9b4ecb7c599b17579bc98ef44e4dbf4771f Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Fri, 20 Nov 2015 22:37:29 +0100 Subject: [PATCH] Add "Socket" module. The Socket module provides an IPC mechanism for guardian, based on a UNIX socket. It contains a server, a client and a message parser function which easily can be re-used. Signed-off-by: Stefan Schantl --- modules/Socket.pm | 117 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 modules/Socket.pm diff --git a/modules/Socket.pm b/modules/Socket.pm new file mode 100644 index 0000000..c8a17c9 --- /dev/null +++ b/modules/Socket.pm @@ -0,0 +1,117 @@ +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 (-s "$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; -- 2.39.2