#!/usr/bin/perl
#
# Problem	In order to analyse a problem, two traces at
#		different locations need to be compared, but 
#		the timestamps are different
# Output	New file with “synchronized” timestamps
# Input		Two capture files (with icmp packets)
# Steps		Make sure to ping between the capture host
# 			Match icmp packets in both files
#			Calculate min and max difference in time
#			Create new file with corrected timestamp#s
#
#
# found on the internet www euronet.nl / sake@euronet.nl
#
# and make some modifications
# versions 0.3
# date: 11.08.2008 
# packetlevel.ch
#


$file1 = shift || die;
$file2 = shift || die;
$file3 = shift;

$tshark  = 'tshark';
$editcap = 'editcap';

$options = "-T fields -e frame.time -e icmp.type -e icmp.ident -e icmp.seq -R icmp";
$cmd1    = $tshark . " -r $file1 " . $options . " 2>/dev/null |";
$cmd2    = $tshark . " -r $file2 " . $options . " 2>/dev/null |";

$t1 = \%times1;
$t2 = \%times2;

sub readline {
   my ($p,$line) = @_;
   chomp $line;
   $line =~ s/\015//;
   ($time,$type,$ident,$seq) = split '\t',$line;
   $id = $ident . "-" . sprintf "%05d",$seq;
   $seq{$id} = 1;
   if( $type == 8 ) {
      $p->{'req'}{$id} = &conv_time($time);
   } else {
      $p->{'resp'}{$id} = &conv_time($time);
   }
}

sub conv_time {
   my ($str) = @_;
   ($dummy,$h,$m,$s) = ($str =~ /^(.*) (\d\d):(\d\d):(\d\d\.\d+)$/);
   return 3600 * $h + 60 * $m + $s;
}


open(F, $cmd1);
while(<F>) {
   &readline($t1, $_);
}
close(F);

open(F, $cmd2);
while(<F>) {
   &readline($t2, $_);
}
close(F);

foreach $seq (sort keys %seq) {
   next unless defined $times1{'req'}{$seq};
   next unless defined $times1{'resp'}{$seq};
   next unless defined $times2{'req'}{$seq};
   next unless defined $times2{'resp'}{$seq};

   $reqdiff= $times2{'req'}{$seq} - $times1{'req'}{$seq};
   $respdiff= $times2{'resp'}{$seq} - $times1{'resp'}{$seq};

   printf "%s : %9.3f %9.3f %9.3f %9.3f -> %15.9f %15.9f\n", $seq,
      $times1{'req'}{$seq},
      $times2{'req'}{$seq},
      $times2{'resp'}{$seq},
      $times1{'resp'}{$seq},
      $reqdiff, $respdiff;

   if( !defined $mindiff ) {
      $mindiff = $reqdiff;
      $maxdiff = $respdiff;
   } else {
      $mindiff = $reqdiff unless $mindiff > $reqdiff;
      $maxdiff = $respdiff unless $maxdiff < $respdiff;
   }
}

$diff = -int( 500000*($mindiff + $maxdiff) ) / 1000000;

printf "\n";
printf "Minimum difference found : %15.9f\n", $mindiff;
printf "Maximum difference found : %15.9f\n", $maxdiff;
printf "\n";

if( abs($diff)<0.000001 ) {
   printf "File \"%s\" and \"%s\" are already time synchronized.\n",$file1, $file2;
} else {
   printf "File \"%s\" needs to be adjusted %f seconds to match file \"%s\"\n",
      $file2, $diff, $file1;

   if( $file3 eq "" ) {
      printf "\nExecute \"editcap -t %f %s <outfile>\" to create a synchronized\nversion of file \"%s\"\n", $diff, $file2, $file2;
   } else {
      $cmd = $editcap . " -t $diff " . $file2 . " $file3";
      system $cmd;
      printf "\nExecuted \"editcap -t %f %s %s\" to create a synchronized\nversion of file \"%s\"\n", $diff, $file2, $file3, $file2;
   }
}
