#!/usr/bin/perl

# ====================================================================
# The Vovida Software License, Version 1.0 
# 
# Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in
#    the documentation and/or other materials provided with the
#    distribution.
# 
# 3. The names "VOCAL", "Vovida Open Communication Application Library",
#    and "Vovida Open Communication Application Library (VOCAL)" must
#    not be used to endorse or promote products derived from this
#    software without prior written permission. For written
#    permission, please contact vocal\@vovida.org.
# 
# 4. Products derived from this software may not be called "VOCAL", nor
#    may "VOCAL" appear in their name, without prior written
#    permission of Vovida Networks, Inc.
# 
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
# NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
# NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
# IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
# 
# ====================================================================
# 
# This software consists of voluntary contributions made by Vovida
# Networks, Inc. and many individuals on behalf of Vovida Networks,
# Inc.  For more information on Vovida Networks, Inc., please see
# <http://www.vovida.org/>.

use Socket;
require "getopts.pl";

&Getopts("n:");

$number = $opt_n;

if($#ARGV < 1) {
  print "Usage:\n";
  print "$0 host1:<local_port1>:<remote_port1> host2:<local_port2>:<remote_port2> [filter_file]\n";
  exit(-1);
}

open(F, $ARGV[0]);
while(<F>) {
  chomp;
  if(/^listener/) {
    #listener  name        port     filter            default-sender
    ($file, $in_name, $in_port, $in_filter_name, $in_default_sender) = split(/\s+/);
    &mksocket($in_port, "IN_$in_name");

    $in_port{$in_name} = $in_port;
    $in_filter{$in_name} = $in_filter_name;
    $in_sender{$in_name} = $in_default_sender;

    
  } elsif(/^sender/) {
    #sender   sender-name   destination-ip   destination-port   listener-name

    ($file, $in_name, $in_port, $in_filter_name, $in_default_sender) = split(/\s+/);
  }

}
close(F);


($host1, $local_port1, $remote_port1) = split(/:/, $ARGV[0]);
($host2, $local_port2, $remote_port2) = split(/:/, $ARGV[1]);

&mksocket($local_port1, S1);
&mksocket($local_port2, S2);

($name,$aliases,$type,$len,$host1_addr) = gethostbyname($host1);
($name,$aliases,$type,$len,$host2_addr) = gethostbyname($host2);

$them_S1 = pack($sockaddr,PF_INET, $remote_port1, $host1_addr);
$them_S2 = pack($sockaddr,PF_INET, $remote_port2, $host2_addr);

($name,$aliases,$type,$len,$host3_addr) = gethostbyname("192.168.10.12");
$them_agent1 = pack($sockaddr,PF_INET, "5010", $host3_addr);
$them_agent2= pack($sockaddr,PF_INET, "5011", $host3_addr);

sub mksocket {
  local($port, $socket) = @_;
  
  $sockaddr = "S n a4 x8";($name,$aliases,$proto) = getprotobyname('udp');
  chomp($hostname  = `hostname`);
  #$hostname  = "192.168.10.12";
  
  ($name,$aliases,$type,$len,$myaddr) = gethostbyname($hostname);
  
  $me   = pack($sockaddr,PF_INET, $port, $myaddr);
  
#  print "myaddr: $myaddr\n";
#  print "port: $port\n";
  
  socket($socket, PF_INET, SOCK_DGRAM, $proto) || die $!;
  bind($socket , $me) || die "died with port $port $!";
  
}


while(1) {
  $rin = '';
  vec($rin, fileno(S1), 1) = 1;
  vec($rin, fileno(S2), 1) = 1;
  #        @bits = split(//, unpack("b*", $rin));
  #	if($bits[fileno(S)]) {
  #		print "got S\n";
  #	}
  if(select($rin, undef, undef, undef)) {
    @bits = split(//, unpack("b*", $rin));
    undef($data);
    undef($new_data);
    if($bits[fileno(S1)]) {
      print "got S1\n";
      $data = "";
      $his_address = recv(S1, $data, 60000, 0);
      if($data) {
	print "-----------------------------\n";
	print "$data";
	print "-----------------------------\n";
        $new_data = &rewrite_S1($data);
        if($new_data) {
	  print "$new_data";
	  print "-----------------------------\n";
	  defined(send(S2,$new_data,0,$them_S1)) || die $!;
        }
      }
    } elsif($bits[fileno(S2)]) {
      print "got S2\n";
      $data = "";
      $his_address = recv(S2, $data, 60000, 0);
      if($data) {
	print "-----------------------------\n";
	print "$data";
	print "-----------------------------\n";
        $new_data = &rewrite_S2($data);
        if($new_data) {
	  print "$new_data";
	  print "-----------------------------\n";
	  defined(send(S1,$new_data,0,$them_S2)) || die $!;
        }
      }
    }
  }
}
#$them = pack($sockaddr,PF_INET, $port, $myaddr);
#send(S,$msg,0,$them) || die $!;

sub renumber_S2 {
  local($_) = $_[0];
  
  s/^([0-9]*)\s([0-9]*)\s/$1 $map{$2} /;
  $map{$number} = $2;
  
  
  return $_;
}
sub renumber_S1 {
  local($_) = $_[0];
  if(s/^([a-zA-Z]*)\s([0-9]*)\s/$1 $number /) {
    $map{$number} = $2;
    $number++;
  }
  return $_;
}

sub rewrite_S1 {
  local($_) = $_[0];

  s/auep/AUEP/;
  s/rqnt/RQNT/;
  s/crcx/CRCX/;
  s/mdcx/MDCX/;
  s/dlcx/DLCX/;
  s/mgcp/MGCP/;

  s/MGCP 0\.1/MGCP 0\.1 NCS 1\.0/;

  s/testID/aaln\/1\@vovida\.com/;
  s/d\/x\(d\)/\[0-9\*\#T\]\(D\), T\(N\)/;
  s/\nd:.*/\nD: (x)/;
  s/\,/, /g;
  s/l\/hf\(n\)\, //;

#  s/\nr:.*//;
#  s/\nd:.*//;
#  s/l\/dl/dl/;

#  s/(\ns:.*)//;
#  $s_param = $1;
#  s/(\nx:.*)/$1$s_param/;

  return $_;
}





sub rewrite_S2 {
  local($_) = $_[0];
  local($nosend) = 0;
  
  if(s/^nosend //) {
    $nosend = 1;
  }
  
  s/o\=.*\ns\=.*\n//;
  s/v\=0/\nv=0/;
  s/aaln\/\*\@vovida\.com/testid/;
  s/aaln\/1\@vovida\.com/testid/;
  s/ NCS 1\.0//;
  #    $_ = &renumber_S1($_);
  
  if(/^([a-z]{4,4})\s+([0-9]+)/i) {
    $x = $2;
    print "saw\n";
    if(/ep0/) {
      print "got: $x\n";
      $host{$x} = 1;
    }
    if(/ep1/) {
      print "got: $x\n";
      $host{$x} = 2;
    }
  }
  
  if(/^([0-9]*) ([0-9]*)/) {
    if($fake{$2}) {
      print " xx fake\n";
      $_ = "";
    }
  }
  
  if(/^auep ([0-9]+)/) {
    $ti = $1;
    $_ = "200 $ti ok\n\n";
    if(/ep1/) {
      defined(send(S2,$_,0,$them_agent1)) || die $!;
    } elsif(/ep2/) {
      defined(send(S2,$_,0,$them_agent2)) || die $!;
    }
  }
  if(/^mdcx/i) {
    print "got mdcx\n";
    if(/ep1/i) {
      $eid = "gw0/ep1\@gg1.sylantro.com";
    } elsif(/ep2/i) {
      $eid = "gw0/ep2\@gg1.sylantro.com";
    }
    
    $xyz = "RQNT 8088 $eid MGCP 0.1\nr: l/hu(n)\nx: 7072\n";
    print "fake-sending $xyz";
    
    defined(send(S1,$xyz,0,$them_S2)) || die $!;
  }
  
  
  s/auep/AUEP/;
  s/rqnt/RQNT/;
  s/crcx/CRCX/;
  s/mdcx/MDCX/;
  s/dlcx/DLCX/;
  s/mgcp/MGCP/;
  s/\*/ep1/;
  
  s/\nO:/\nO: /i;
  s/\nX:/\nX: /i;

  s/hd/l\/hd/;
  s/hu/l\/hu/;

  s/\,l\/hf\(n\)//ig;
  if(y/\0//d) {
    print "killed \\0!\n";
  }
  
  s/\n\s+\n/\n\n/g;
  y/\r//d;
  s/\n+$/\n/;
  s/\n\n$/\n/g;
  #    s/\n+/\n/g; 
  s/\n/\r\n/g;
  if(s/([^\r\n])(\r\n)+$/$1\r\n/g) {
    print "2 ate \\r\\n\n";
  }
  
  if(/^rqnt/i) {
    s/,d\/x\(n\)//i;
   }


   if(/^crcx/i) {
	if(!/v\=0/i) {
		s/sendrecv/recvonly/;

	}



   }

  s/ep1\@vovida.com/testid\@newton.private.vovida.com/;

  s/RM:restart//;

   if($nosend) {
	print "nosend:\n$_----------\n";
	$_ = "";
    }
    return $_;
}

__END__

  
  #    $_ = &renumber_S2($_);
  
  s/\nO: hd/\nO: l\/hd/;
  s/\nO: hu/\nO: l\/hu/;

  s/auep/AUEP/;
  s/rqnt/RQNT/;
  s/crcx/CRCX/;
  s/mdcx/MDCX/;
  s/dlcx/DLCX/;
  s/mgcp/MGCP/;
  
  
  if(/c\=in ip4 ([0-9\.]+)/i) {
    $x = $1;
    s/(v\=0.*\n)/$1o\=\- 0 0 in ip4 $x\ns\=Vovida Gateway\n/i;
  }
  s/(m\=.*\n)/$1\n/i;
  
  if(/^fake [a-zA-Z]+ ([0-9]+)/i) {
    $fake{$1} = 1;
    s/^fake //;
  }
  
  
#  y/A-Z/a-z/;
  
  s#\r##g;			
  
  if(/ep0\@/) {
    print "sending port 1:\n$_----------";
    defined(send(S2,$_,0,$them_agent1)) || die $!;
  } elsif(/ep1\@/) {
    print "sending port 2:\n$_----------";
    defined(send(S2,$_,0,$them_agent2)) || die $!;
  }
  
  if(/^[0-9]/)  {
    /^([0-9]+)\s+([0-9]+)\s/;
    print "xyz $2\n";
    if($host{$2} == 1) {
      print "tar: $host{$2}\n";
      defined(send(S2,$_,0,$them_agent1)) || die $!;
    }	
    if($host{$2} == 2) {
      print "tar: $host{$2}\n";
      defined(send(S2,$_,0,$them_agent2)) || die $!;
    }	
    
  }
  $_ = "";
