Add "Socket" module.
authorStefan Schantl <stefan.schantl@ipfire.org>
Fri, 20 Nov 2015 21:37:29 +0000 (22:37 +0100)
committerStefan Schantl <stefan.schantl@ipfire.org>
Fri, 20 Nov 2015 21:37:29 +0000 (22:37 +0100)
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 <stefan.schantl@ipfire.org>
modules/Socket.pm [new file with mode: 0644]

diff --git a/modules/Socket.pm b/modules/Socket.pm
new file mode 100644 (file)
index 0000000..c8a17c9
--- /dev/null
@@ -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;