#!/usr/bin/perl

use strict;
use warnings;

use FindBin;
use lib "$FindBin::Bin/../../lib";
use Wigo::Probe qw/:all/;

use Time::HiRes qw/time/;
use Net::NTP;

###
# DEFAULT CONFIG
###

my $conf = {
    'ntp_server'    => "fr.pool.ntp.org",
    'port'          => 123,
    'warning'       => 10,
    'critical'      => 300,
};

init( config => $conf );

my %h;
persist or persist({ 'countFailed' => 0 });

my ($c1,$c2);
for( my $try = 1; $try <= 3; $try++ )
{
    # Net::NTP has no timeout.
    eval
    {
        local $SIG{"ALRM"} = sub { die "ntp timeout\n"; };
        alarm 5 ;
        $c1 = time;
        %h = get_ntp_response( config->{'ntp_server'}, config->{'port'} );
        $c2 = time;
        alarm 0 ;
    };

    if( $@ )
    {
        if( $try == 3 )
        {
            persist->{'countFailed'}++;

            if( persist->{'countFailed'} >= 3 )
            {
                status 500;
            }
            else
            {
                status 100 + persist->{'countFailed'};
            }

            detail->{'nbTries'} = $try;
            message sprintf( "NTP server %s:%s is unreachable : %s", config->{'ntp_server'}, config->{'port'} || 123 ,  $@ );
            output 1;
        }
    }
    else
    {
        persist->{'countFailed'} = 0;
        detail->{'nbTries'} = $try;
        last;
    }
}

my $responseTime = sprintf "%.3f", ( $c2 - $c1 ) * 1000;

my $s1 = $h{'Receive Timestamp'};
my $s2 = $h{'Transmit Timestamp'};

# Trip Time
my $tt = ( ( $c2 - $c1 ) - ( $s2 - $s1 ) ) / 2;

# Real time
my $rt = $s2 + $tt ;

# Delta
my $delta = $c2 - $rt ;
my $absdelta = abs( $delta ) ;
$delta = sprintf "%.3f", $delta;

if( $absdelta > config->{'critical'} )
{
    status  300;
    message sprintf( "Server clock is not correctly set ( drift is %s seconds )", $delta );
}
elsif( $absdelta > config->{'warning'} )
{
    status 200;
    message sprintf( "Server clock is not correctly set ( drift is %s seconds )", $delta );
}
else
{
    message sprintf( "Server clock is correctly set ( drift is %s seconds )", $delta );
}

detail->{'drift'}           = $delta . " seconds";
detail->{'response_time'}   = $responseTime . " ms";
detail->{'ntp_server'}      = config->{'ntp_server'};

add_metric { "Tags" => { 'metric' => 'drift' }, 'Value' => $delta };
add_metric { "Tags" => { 'metric' => 'response_time' }, 'Value' => $responseTime };

output 0;
