in reply to Re: IPC named pipe issue with nstore_fd
in thread IPC Design problem
Thanks for the tips, would you please expand on the "style/idiom issues"?
I did not put much effort in applying best practices in the test script but I tried to do better in the code, what should I try to improve?
also, I finaly nailed it down I think. I am still looking for a way to send serialized hash without bad things happening due to newline though...
package Security::Monitoring::Messaging; use Security::Monitoring::Messaging::Messenger; use 5.14.2; use strict; use warnings; use Proc::Daemon; use Carp qw(carp croak); use Storable qw(fd_retrieve); use POSIX qw(mkfifo); use File::Spec::Functions; use Cwd; use IO::Socket::UNIX; use IO::Socket::INET; my $class = "Security::Monitoring::Messaging::Messenger"; =head1 NAME Security::Monitoring::Messaging - The great new Security::Monitoring:: +Messaging! =head1 VERSION Version 0.01 =cut our $VERSION = '0.01'; =head1 SYNOPSIS you want to call this script using Proc::Daemon exec, that way it will + be able to do its work from the background. Whenever another script needs to a +sk for a messenger (most of theses orders should be made at start time dependin +g on the configuration) it should nstore a hash to the messenger unit named pip +e. my %params = ( input=>{name=>'filename', type=>'unix_socket|network_socket|named_pipe', #where it will listen; listen=>$queue_size_for_listen;#for sockets local_addr=>'what it says on the can',#for network socket local_port=>'idem',#for network socket proto=>'tcp|udp',#for network socket } output1=>{name=>'filename', type=>'unix_socket|network_socket|named_pipe, bind=>address,#if network socket Local=>'pathname to local buffer',#unix socket only Listen=>$queue_size_for_listen',#for sockets peer_addr=>'address", ... ... }, output2=>{...}, ... outputn=>{...}, ); nstore_fd \%params $messaging_named_pipe; a messaging daemon should be started. =head1 DESCRIPTION this module is a daemon that listens for messenger requests and spawn +little messenger daemon to handle IPC between units (such as report communica +tion between the reporting unit and the monitoring unit) it is done so to a +llow each unit to run on a different server. =head1 SUBROUTINES/METHODS run =head2 run this is the main function, even if this is a pm file it also is a self contained program. One can run the whole module on one server or only +part of it and have it interact with other servers. An Instance of the Messagi +ng daemon has to run on each and every server that supports one of the ma +in units (ie reporting unit, config unit, mailer unit, monitoring unit and db interaction unit) =cut =head3 sample param hash my %params = ( input=>{name=>'filename', type=>'unix_socket|network_socket|named_pipe', #where it will listen; listen=>$queue_size_for_listen;#for sockets peer=>'peer_buffer_file_name',#unix sockets local_addr=>'what it says on the can',#for network socket local_port=>'idem',#for network socket proto=>'tcp|udp',#for network socket } output1=>{name=>'filename', type=>'unix_socket|network_socket|named_pipe, bind=>address,#if network socket Local=>'pathname to local buffer',#unix socket only Listen=>$queue_size_for_listen',#for sockets peer_addr=>'address", ... ... }, output2=>{...}, ... outputn=>{...}, ); =cut sub run { #setup part my $request_file_name = shift;#named pipe to which the Messenging +daemon will #listen for messenger spawn requests. my $log_file_name = shift; if (!defined($log_file_name)){ $log_file_name = '/dev/null'; } open my $log, '>>',$log_file_name or croak "could not open log_fil +e"; if (!defined($request_file_name)){ croak "can not run without something to listen to!\n"; } mkfifo($request_file_name,0777)||croak "could not open named pipe +: $!"; my %children = (); my $pid; my %messenger_params; print $log "I'm $$ and starting to run\n"; #running part ABORT:while(1){ open my $fh,'<',$request_file_name; my $params; eval{$params = fd_retrieve($fh)}; if($@){ print "continuing after error $@"; close $fh; redo; } close $fh; print "params input name = $params->{input}->{name}\n"; $messenger_params{input}->{name} = $params->{input}->{name}; $messenger_params{input}->{type} = $params->{input}->{type}; #put the input data into the messenger params hash given ($params->{input}->{type}){ when('unix_socket'){ $messenger_params{input}->{fh} = IO::Socket::UNIX::->n +ew( Type=>SOCK_STREAM, Local=>$params->{input}->{name}, Listen=>$params->{input}->{Listen}, ); } when('network_socket'){ if(!exists($params->{input}->{local_addr})||!exists($p +arams->{input}->{local_port})){ carp "I need a peer addr and a peer port to create + a socket!"; goto ABORT; } $messenger_params{input}->{fh} = IO::Socket::INET->new +( Listen=>$params->{input}->{Listen}, LocalAddr=>$params->{input}->{loca_addr}, Proto=>$params->{input}->{proto}, LocalPort=>$params->{input}->{local_port}, ); } when('named_pipe'){ mkfifo($params->{input}->{name},0777)||carp "could not + open named pipe : $!"; open $messenger_params{input}->{fh}, '<',$params->{input}->{name} or carp "could not open n +amedpipe for input"; } } #putting the output subhashes into the messenger params hash my @keys = keys %{$params->{output}}; OUTPUT: foreach my $key (@keys){ $messenger_params{output}->{$key}->{type} = $params->{output}->{$key}->{type}; $messenger_params{output}->{$key}->{name} = $params->{output}->{$key}->{name}; given ($params->{output}->{$key}->{type}){ when('unix_socket'){ $messenger_params{output}->{$key}->{fh} = IO::Socket::UNIX->new( Type=>SOCK_STREAM, Local=>$params->{output}->{$key}->{name}, Listen=>$params->{output}->{$key}->{listen +}, ); } when('network_socket'){ $messenger_params{output}->{$key}->{fh} = IO::Socket::INET->new( LocalAddr=>$params->{output}->{$key}->{loc +al_addr}, LocalPort=>$params->{output}->{$key}->{loc +al_port}, Proto=>$params->{output}->{$key}->{proto}, Listen=>$params->{output}->{$key}->{listen +}, ); } when('named_pipe'){ mkfifo($messenger_params{output}->{$key}->{name},0 +777)||carp "could not open named pipe : $!"; } } } $pid = fork(); if (!$pid){#I'm the son my $messenger = $class->new(\%messenger_params); print "starting to relay\n"; $messenger->relay; } else{ print "$pid forked\n"; $children{$pid} = 1; } } } if(!defined(caller())){ my $filename = shift; my $logfile = shift; &run($filename,$logfile); }
|
|---|