package Security::Monitoring::Messaging::Messenger; use 5.14.2; use strict; use warnings; use Carp qw(carp croak); use IO::Socket::INET; use IO::Socket::UNIX; =head1 NAME Security::Monitoring::Messaging::Messenger - The great new Security::Monitoring::Messaging::Messenger! =head1 VERSION Version 0.01 =cut our $VERSION = '0.01'; =head1 SYNOPSIS $messenger->new($param_hash_ref); $messenger->relay; =head1 DESCRIPTION this module provides the messenger class, instances of this class will be used in small daemon to handle message passing between the main units of the program, thus allowing each unit to interact as if on the same machine of each other. the Main Messaging daemon creates smaller daemons when asked to do so (at start time such order will come from the config files, during run time it will listen to a named pipe for new orders) =head1 SUBROUTINES/METHODS =head2 new summons a new instance of the Messenger class =head3 use my %outputs = ( $whatevername => $filehandle, $whatevername2=>$anotherfilehandle, ); my %params = ( input=>$filehandle, output = \%output; ); my $messenger = $class->new(\%params); =cut sub new(\%) { my ($class,$params) = @_; my $self = {}; bless $self, $class; if (!defined $params){ croak "no params, cant create new messenger\n"; } $self->_init($params); return $self; } =head2 _init init function for messenger instances =cut sub _init { my($self,$params) = @_; $self->{input}->{type} = $params->{input}->{type}; $self->{input}->{fh} = $params->{input}->{fh}; $self->{input}->{name} = $params->{input}->{name}; my @outputs = keys $params->{output}; foreach my $key (@outputs){ print "init for $params->{output}->{$key}->{name}"; $self->{output}->{$key}->{type} = $params->{output}->{$key}->{type}; $self->{output}->{$key}->{fh} = $params->{output}->{$key}->{fh}; $self->{output}->{$key}->{name} = $params->{output}->{$key}->{name}; } } =head2 _write this function is used by the relay sub for the messaging job =cut sub _write{ my $self = shift; if(!ref $self){ croak "can not do that as a class!"; } my $input = shift; #writes the input to every output using different method depending on the #type of output my @keys = keys $self->{output}; foreach my $key (@keys){ if(!defined($self->{output}->{$key}->{fh}) && !$self->{output}->{$key}->{type} eq 'named_pipe'){ croak "undefined fh for key $key\n"; } given($self->{output}->{$key}->{type}){ when('named_pipe'){ open my $handle ,'>',$self->{output}->{$key}->{name} or croak "could not open output handle"; print $handle $input; close $handle; } when('unix_socket'){ my $server = $self->{output}->{$key}->{fh}; if(!exists $self->{output}->{$key}->{socket}){ $self->{output}->{$key}->{socket}= $server->accept() or croak "$!"; } my $socket = $self->{output}->{$key}->{socket}; print $socket $input; } when('network_socket'){ my $server = $self->{output}->{$key}->{fh}; if(!exists $self->{output}->{$key}->{socket}){ $self->{output}->{$key}->{socket} = $server->accept() or croak "$!"; } print "printing to output"; my $socket = $self->{output}->{$key}->{socket}; print $socket $input; } } } } =head2 relay this function is called just after forking : it starts the actual messaging, the daemon waits for input and transmit to all its outputs =head3 use $messenger->relay; =cut sub relay{ my $self = shift; if(!ref($self)){ croak "can not call relay from a class"; } my $handle = $self->{input}->{fh}; #starts reading from input given ($self->{input}->{type}){ when ('named_pipe'){ open $handle,'<',$self->{input}->{name}; while(<$handle>){ $self->_write($_); } } when('unix_socket'){ my $socket = $handle->accept()||croak "$!"; while(<$socket>){ my $data = $_; print "I receive $data\n"; $self->_write($data); } } when('network_socket'){ print "gonna try and listen on network socket named $self->{input}->{name}\n"; my $socket = $handle->accept()||croak"$!"; print "listening\n"; while(<$socket>){ my $data = $_; print "I receive $data\n"; $self->_write($data); } } } }