--- projects/cms/source/host/ihost-perl/ihost.pl 2001/02/28 10:52:16 1.19 +++ projects/cms/source/host/ihost-perl/ihost.pl 2001/03/16 18:25:59 1.32 @@ -9,8 +9,8 @@ # methods as you see fit. # - pjm2@ukc.ac.uk # -# $Author: tdb $ -# $Id: ihost.pl,v 1.19 2001/02/28 10:52:16 tdb Exp $ +# $Author: pjm2 $ +# $Id: ihost.pl,v 1.32 2001/03/16 18:25:59 pjm2 Exp $ #------------------------------------------------------------ $| = 1; @@ -33,6 +33,8 @@ use vars qw ( $filter_addr $file_list $fqdn + $pidfile + $retry_wait ); if (@ARGV != 2) { @@ -43,7 +45,12 @@ $filter_manager_addr = $ARGV[0]; $filter_manager_port = $ARGV[1]; $seq_no = 1; +$retry_wait = 6; +# write our PID to a file +$pidfile = "/var/tmp/ihost.pid"; +&write_pid(); + &tcp_configure(); &send_udp_packet(); @@ -71,10 +78,23 @@ while (1) { `sleep $delay`; } +# we'll probably never get here... +`rm -f $pidfile`; exit(0); #----------------------------------------------------------------------- +# wait_then_retry +# Waits for the period of time specified in $retry_wait, then attempts +# to reconfigure with the server. +#----------------------------------------------------------------------- +sub wait_then_retry() { + print "Will retry configuration with filter manager in $retry_wait seconds.\n"; + `sleep $retry_wait`; +} + + +#----------------------------------------------------------------------- # tcp_configure # Establishes a TCP connection to the specified i-scream filter manager. # The host then requests details from the server, such as the intervals @@ -82,96 +102,150 @@ exit(0); #----------------------------------------------------------------------- sub tcp_configure() { - my($sock) = new IO::Socket::INET( - PeerAddr => $filter_manager_addr, - PeerPort => $filter_manager_port, - Proto => 'tcp' - ); - if (!defined $sock) { - print "IHOST ERROR: Could not connect to $filter_manager_addr:$filter_manager_port.\n"; - print "Please check that there is an i-scream server at this address.\n"; - print "Program ended.\n"; - exit(1); - } + while (1) { + my($sock) = new IO::Socket::INET( + PeerAddr => $filter_manager_addr, + PeerPort => $filter_manager_port, + Proto => 'tcp' + ) or die "Cannot connect!"; + if (!defined $sock) { + print "IHOST ERROR: Could not connect to $filter_manager_addr:$filter_manager_port.\n"; + print "Please check that there is an i-scream server at this address.\n"; + wait_then_retry(); + next; + } - # Now run through the configuration process... - my($response); + # Now run through the configuration process... + my($response); - print $sock "STARTCONFIG\n"; - $response = <$sock>; - if (!chop $response eq "OK") { - print "The i-scream server rejected the STARTCONFIG command. Terminated."; - exit(1); - } + print $sock "STARTCONFIG\n"; + $response = <$sock>; + if ($response && !($response eq "OK\n")) { + print "The i-scream server rejected the STARTCONFIG command.\n"; + close($sock); + wait_then_retry(); + next; + } - print "Config started okay.\n"; + print "Config started okay.\n"; - print $sock "LASTMODIFIED\n"; - $response = <$sock>; - chop $response; - $last_modified = $response; + print $sock "LASTMODIFIED\n"; + $response = <$sock>; + if (!$response) { + print "The i-scream server did not return anything for the LASTMODIFIED command.\n"; + close($sock); + wait_then_retry(); + next; + } + chop $response; + $last_modified = $response; - print "Config last modified: ". (scalar localtime $last_modified/1000) . "\n"; + print "Config last modified: ". (scalar localtime $last_modified/1000) . "\n"; - print $sock "FILELIST\n"; - $response = <$sock>; - chop $response; - $file_list = $response; + print $sock "FILELIST\n"; + $response = <$sock>; + if (!$response) { + print "The i-scream server did not provide a configuration file list.\n"; + close($sock); + wait_then_retry(); + next; + } + chop $response; + $file_list = $response; - print "File list obtained: $file_list\n"; + print "File list obtained: $file_list\n"; - print $sock "FQDN\n"; - $response = <$sock>; - chop $response; - $fqdn = $response; + print $sock "FQDN\n"; + $response = <$sock>; + if (!$response) { + print "The i-scream server did not tell us our FQDN.\n"; + close($sock); + wait_then_retry(); + next; + } + chop $response; + $fqdn = $response; - print "FQDN returned: $fqdn\n"; + print "FQDN returned: $fqdn\n"; - print $sock "UDPUpdateTime\n"; - $response = <$sock>; - chop $response; - $udp_update_time = $response; + print $sock "UDPUpdateTime\n"; + $response = <$sock>; + if (!$response) { + print "The i-scream server did not give us a UDPUpdateTime.\n"; + close($sock); + wait_then_retry(); + next; + } + chop $response; + $udp_update_time = $response; - print $sock "TCPUpdateTime\n"; - $response = <$sock>; - chop $response; - $tcp_update_time = $response; + print $sock "TCPUpdateTime\n"; + $response = <$sock>; + if (!$response) { + print "The i-scream server did not give us a TCPUpdateTime.\n"; + close($sock); + wait_then_retry(); + next; + } + chop $response; + $tcp_update_time = $response; - print "UDP packet period: $udp_update_time seconds.\nTCP heartbeat period: $tcp_update_time seconds.\n"; + print "UDP packet period: $udp_update_time seconds.\nTCP heartbeat period: $tcp_update_time seconds.\n"; - print $sock "ENDCONFIG\n"; - $response = <$sock>; - chomp $response; - if (!$response eq "OK") { - print "ENDCONFIG command to server failed. Terminated.\n"; - exit(1); - } + print $sock "ENDCONFIG\n"; + $response = <$sock>; + if ($response && !($response eq "OK\n")) { + print "ENDCONFIG command to server failed. Terminated.\n"; + close($sock); + wait_then_retry(); + next; + } - print "Config ended.\n"; + print "Config ended.\n"; - print $sock "FILTER\n"; - $response = <$sock>; - chop $response; - $response =~ /(.*);(.*);(.*)/; - ($filter_addr, $udp_port, $tcp_port) = ($1, $2, $3); + print $sock "FILTER\n"; + $response = <$sock>; + if (!$response) { + print "Failed: Could not get a filter address from the filter manager.\n"; + close($sock); + wait_then_retry(); + next; + } + chop $response; + $response =~ /^(.*);(.*);(.*)/; + if ($response eq "ERROR") { + print "There are no active configured filters for your host.\n"; + close($sock); + wait_then_retry(); + next; + } + ($filter_addr, $udp_port, $tcp_port) = ($1, $2, $3); + unless (defined($filter_addr) && defined($udp_port) && defined($tcp_port)) { + print "Failed: Filter address response from server did not make sense: $response\n"; + close($sock); + wait_then_retry(); + next; + } - print "Got filter data ($filter_addr, $udp_port, $tcp_port)\n"; + print "Got filter data ($filter_addr, $udp_port, $tcp_port)\n"; - print $sock "END\n"; - $response = <$sock>; - chop $response; - if ($response eq "OK") { - print "Host successfully configured via TCP.\n" - } - else { - print "The server failed the host configuration on the END command."; - exit(1); - } + print $sock "END\n"; + $response = <$sock>; + if ($response && ($response eq "OK\n")) { + print "Host successfully configured via TCP.\n" + } + else { + print "The server failed the host configuration on the END command.\n"; + close($sock); + wait_then_retry(); + next; + } - close($sock); + close($sock); - print "Configuration finished sucessfully!\n"; - + print "Configuration finished sucessfully!\n"; + last; + } return; } @@ -265,13 +339,11 @@ EOF # Make the packet smaller by stripping out newlines and leading spaces. $xml =~ s/\n\s*//g; -print $xml; - my($sock) = new IO::Socket::INET ( PeerPort => $udp_port, PeerAddr => $filter_addr, Proto => 'udp' - ) or die "Socket: $!\n"; + ) or die "Could not send UDP: $!\n"; print $sock $xml or die "Could not send UDP packet: $!\n"; close($sock); @@ -295,9 +367,10 @@ sub send_tcp_heartbeat() { PeerAddr => $filter_addr, PeerPort => $tcp_port, Proto => 'tcp' - ); + ) or return; if (!defined $sock) { print "IHOST WARNING: Failed to deliver a heartbeat to the i-scream filter.\n"; + &tcp_configure(); return; } @@ -306,56 +379,70 @@ sub send_tcp_heartbeat() { print $sock "HEARTBEAT\n"; $response = <$sock>; - chop $response; - if (!$response eq "OK") { + if (!$response eq "OK\n") { close($sock); print "Server gave wrong response to HEARTBEAT: $response\n"; + &tcp_configure(); return; } print $sock "CONFIG\n"; $response = <$sock>; - chop $response; - if (!$response eq "OK") { + if (!$response eq "OK\n") { close($sock); print "Server gave wrong response to CONFIG: $response\n"; + &tcp_configure(); return; } print $sock "$file_list\n"; $response = <$sock>; - chop $response; - if (!$response eq "OK") { + if (!$response eq "OK\n") { close($sock); print "Server gave wrong response to file list: $response\n"; + &tcp_configure(); return; } print $sock "$last_modified\n"; $response = <$sock>; - chop $response; - if ($response eq "ERROR") { + if ($response eq "ERROR\n") { close($sock); + print "Server configuration changed. Reconfiguring with filter manager.\n"; &tcp_configure(); return; } - if (!$response eq "OK") { + if (!$response eq "OK\n") { close($sock); print "Server gave wrong response to HEARTBEAT: $response\n"; + &tcp_configure(); return; } print $sock "ENDHEARTBEAT\n"; $response = <$sock>; - chop $response; - if (!$response eq "OK") { + if (!$response eq "OK\n") { close($sock); print "Server gave wrong response to ENDHEARTBEAT: $response\n"; + &tcp_configure(); return; } close($sock); print "^"; + + return; +} + +#----------------------------------------------------------------------- +# write_pid +# Writes the PID (process ID) of this instance to $pidfile. +# This is then used by a seperate script to check (and restart) ihost. +#----------------------------------------------------------------------- +sub write_pid() { + open PID, ">$pidfile"; + print PID $$; + close PID; return; }