#!/usr/bin/perl -w
# a UDP client that connects to a host and sends a 'PING' message and prints the response fro the server.
# - Don Mahurin
#
# usage: perl pingpong.pl HOST PORT

$|++;

eval 'sub SYS_gettimeofday () {78;}';

my ($host, $port, $lport) = @ARGV;
use strict;
use IO::Socket;
$port = 4242 unless(defined($port));

my $message = IO::Socket::INET->new(Proto=>"udp",LocalPort=>$lport,PeerPort=>$port,PeerAddr=>"$host")
 or die "Can't make UDP socket: $@";

my $SO_TIMESTAMP = 29;
setsockopt($message, SOL_SOCKET, $SO_TIMESTAMP, pack("l", 1));

my($fin, $rout,$wout,$eout) = ('');
vec($fin,fileno($message),1) = 1;
my $sendstr = $ENV{SENDSTR};
$sendstr = "Ping!" unless(defined($sendstr));
while(1)
{
print "sending udp ping\n";
$message->send($sendstr);
print "sent from " . $message->sockport . "\n";

my(@t1) = get_local_time();

my ($datagram,$flags);
$SIG{ALRM} = sub {};
alarm(5);
print "before\n";

my $n = $message->recv($datagram,42,$flags)
	if (select($rout=$fin, undef, $eout=$fin, 0));
print "after r\n";
my(@t2) = get_local_time();
my($tds, $tdu) = time_diff(@t2, @t1);
if(defined($datagram)){
print "Got message ($tds, $tdu) from ", $message->peerhost,", flags ",$flags || "none",": $datagram\n" if(defined($n));
}
sleep(1);
}

sub get_local_time
{
        my ($timeval) = pack("I2", 0, 0);
        my ($timezone) = pack("L2", 0, 0);
        my ($r) = syscall(&SYS_gettimeofday, $timeval, $timezone);
        return (unpack("I2",$timeval));
}

sub time_diff
{
        my($t1, $u1, $t2, $u2) = @_;
        my $t = $t1 - $t2;
        my $u = $u1 - $u2;
        if($t > 0 && $u < 0) { return($t - 1, $u + 1000000); }
        elsif($t < 0 && $u > 0) { return($t + 1, $u - 1000000); }
        else { return ($t, $u) };
}

