#!/usr/bin/perl

#
# mgcsim
# MGC dummy (receive) simulator
# Copyright (C) 2000 Vikram Visweswaraiah <vikram@acc.com>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
# $Id: mgcsim,v 1.1 2001/05/25 21:40:33 vikram Exp $


=pod SCRIPT CATEGORIES

Networking

=pod PREREQUISITES

This script requires C<strict> and C<IO::Socket>.

=pod README

This script, though standalone, is intended to be used with `mgcpgen' also 
available at CPAN scripts. These scripts were mainly developed to test
parsing on a Media Gateway supporting MGCP 1.0. They have been used 
extensively in real test environments for call setup and debugging. Given 
their simple functionality, bugs should be minimal - please let me
<vikram@acc.com> know if you find bugs and/or if you find these 
scripts useful. 

=head1 NAME

mgcsim - dummy MGC (receive) simulator.

=head1 SYNOPSIS

B<mgcsim>
[B<-p><localport>]
[B<-s>]

B<mgcsim>
[I<-h>]

=head1 DESCRIPTION

B<mgcsim> starts up a dummy MGC simulator that responds to commands sent 
from an external MG. Usually the only commands that an MG can send are 
RSIPs (Restart In Progress) or DLCXs (Delete Connection). Regardless of 
the validity of the messages, this simulator will extract the transaction
Id (tid) from the message and send a 200 <tid> OK to the MG. 

=head1 OPTIONS

=over 8

=item p

Specify a local port to bind to. The default port is 2727. There should be
no space between B<-p> and the port number.

=item s

Start up in continuous mode, i.e keep on waiting for messages and send
responses. This is common usage.

=item h

Print usage summary.

=back

=head1 EXAMPLES

    mgcsim -p5000  (Bind to local port 5000)
    mgcsim -p3250 -s (Bind to local port 3250 
		      and run continuously)

=head1 ENVIRONMENT

No special environment variables are used.

=head1 SEE ALSO

mgcpgen(1), rfc2705

=head1 AUTHOR

Vikram Visweswaraiah (vikram@acc.com)

=cut


require 5.001;
use strict;
use IO::Socket;


my $max_msglen = 600;
my $sep = '-------------------------------------------------';
my $infinite = 0;
my $mgcp_port;

if ($ARGV[0] =~ /-p(\d+)/)
{
    $mgcp_port = $1;
    shift;
}
else
{
    $mgcp_port = 2727;
}

if ($ARGV[0] =~ /-s/)
{
    $infinite = 1;
}

&usage if ($ARGV[0] =~ /(-h|-\?)/);

sub usage {
    die<<END;
Usage: $0 [-p<lclport>] [-s] 

Start up a dummy MGC. Wait for commands from some MG. Usually this
is only RSIP or DLCX. Extract the transaction Id from the message 
and send a 200 <tid> OK to the MG.
If optional -s is specified as first argument, then
the simulator never exits and runs in continuous mode.
END
}


# Start up MGC on UDP port 2427
my $mgc = IO::Socket::INET->new(
				Proto    => "udp",
				Type => SOCK_DGRAM,
				LocalPort => $mgcp_port,
				)
    or die "Cannot start up MGC (maybe port $mgcp_port is in use, try -h)\n";

# Get local addr/port
my $lcladdr = "localhost";
my $lclport = $mgc->sockport();

print "MGC \($lcladdr\:$lclport\) started up, waiting for MG commands...\n";

for(;;)
{
    rsip_or_dlcx_rcv();
    if (!$infinite)
    {
	last;
    }
}

sub rsip_or_dlcx_rcv {
    my ($buf, @t, $port, $tid, $respbuf, $rem_addr);
# Wait for RSIP.
    $mgc->recv($buf, $max_msglen); 
    @t = localtime;

# Get MG address and port
    $port = $mgc->peerport();
    $rem_addr = inet_ntoa($mgc->peeraddr());

# Make sure it's RSIP/DLCX/NTFY in the right format.
    if ($buf =~ /^(NTFY|RSIP|DLCX)\s+(\d{1,9})/i)
    {
	$tid = $2;
    }
    else
    {
	print $buf;
	die "Invalid message from $rem_addr:$port\n";
    }

    print "$sep\n";
    print "$t[2]:$t[1]:$t[0] $rem_addr:$port ---> $lcladdr:$lclport\n";
    print "$sep\n";
    print $buf;

# Send ok to kickstart MG
    $respbuf = "200 $tid OK\n";
    print "$sep\n";
    @t = localtime;
    print "$t[2]:$t[1]:$t[0] $lcladdr:$lclport ---> $rem_addr:$port\n";
    print "$sep\n";
    print $respbuf;

    $mgc->send($respbuf);

}


