package Monitor::rpc_ping;

require 5.002;
require Exporter;

use strict;
use Monitor::rpc;

@Monitor::rpc_ping::ISA = qw(Monitor::Monitor);

%rpc_ping::progs = (
    "mount", "100005:0:mount",
    "nfs", "100003:0:nfs",
    "nlm", "100021:0:nlm",
    "yp", "100004:0:yp",
    "yppasswd", "100009:0:yppasswd",
    "portmapper", "10000:0:portmapper"
    );


sub new
{
    my ($this, $timeout) = @_;
    my( $rpc );
    my  $class = ref($this) || $this;
    my  $self = {};

    bless($self, $class);

    ($timeout=1) unless( $timeout );
    $self->{"timeout"} = $timeout;

    my( @bla)  = ();
    $self->{"htable"} = \@bla;
    $rpc = $self->{"rpc"} = Monitor::rpc->new( $timeout );
    $rpc->{"auth_data"} = $rpc->{"ver_auth_data"} = "";
    $rpc->{"auth_flavor"} = $rpc->{"ver_auth_flavor"} = $rpc::AUTH_NULL;

    return($self);
}


sub DESTROY {
    my( $self ) = @_;

    close( $self->{"fh"} );
}



sub add_host {
    my( $self, $item, $ip, $prog, $version, $proto ) = @_;
    my( $htable ) = $self->{"htable"};
    my( $call, $port, $comment );

    ($version = 1) unless( defined $version );
    return( undef ) unless( defined $rpc_ping::progs{$prog} );
    ($prog, $call, $comment) = split( ":", $rpc_ping::progs{$prog} );
    $port = $self->{"rpc"}->portmap( $ip, $prog, $version, $proto );
    print "prog: $prog, call:$call, port:$port\n" if( $BigSister::common::dl>2 );
    
    push( @$htable, "$ip\x00$prog\x00$version\x00$port\x00$call\x00$item\x00$comment\x00$proto" );
}




sub check
{
    my ($self) = @_;
    my ($i, @list, %result, $timeout, $res, $rbits, $finish_time, $msg, $saddr, $nfound );
    my( $htable ) = $self->{"htable"};
    my( $host, $port, $prog, $version, $call, $item, $rpc, $comment, $proto );
    my( %msg, $ok, $newport, $max );

    $timeout = $self->{"timeout"};
    @list = @$htable;
    $rpc = $self->{"rpc"};

    for( $i=0; $i<=$#list; $i++ ) {
	undef $host;
	undef $port;
	undef $prog;
	undef $version;
	undef $call;
	($host,$prog,$version,$port,$call, $item, $comment,$proto) = split( "\x00", $list[$i] );
	print "checking rpc($host,$prog,$version,$port,$call,$item)\n" if( $BigSister::common::dl>4 );
	unless( $port ) {
	    $port = $self->{"rpc"}->portmap( $host, $prog, $version, $proto );
	    if( $port ) {
		$list[$i] = join( "\x00", $host,$prog,$version,$port,$call, $item, $comment,$proto );
	    }
	    else {
		$self->report( $item, $BigSister::common::status_codes{"yellow"}, "rpc ".$comment." UNKNOWN PROG" );
		next;
	    }
	}
	$rpc->{"version"} = $version;
	$rpc->{"prog"} = $prog;
	$max = 5;
	while($max--) {
	    $rpc->{"port_num"} = $port;
	    %msg = $rpc->call( $host, $call, "" );
	    $ok = (%msg && $msg{"stat"} && ($msg{"accepted_stat"}==$rpc::SUCCESS) );
	    last if( $ok );
	    print "rpc: failed - trying to re-map port\n" if( $BigSister::common::dl>4 );
	    $newport = $self->{"rpc"}->portmap( $host, $prog, $version, $proto );
	    if( $port != $newport ) {
		$port = $newport;
		$list[$i] = join( "\x00", $host,$prog,$version,$port,$call, $item, $comment,$proto );
		print "rpc: new port is $port\n" if( $BigSister::common::dl>4 );
	    }
	    else { last; }
	}
	$self->report( $item, $ok?$BigSister::common::status_codes{"green"}:$BigSister::common::status_codes{"red"}, 
			"rpc ".$comment." ".($ok?"OK":"FAILURE") );
    }
}

1;
