#!/usr/bin/perl -w

use strict;
use IO::Socket;
use Getopt::Long;
$|=1;

my $host = "localhost";
my $username = "user";
my $password = "pass";

my (
	$version, $response, $message, $line, $chan1, $chan2,
	$verbose, $help, $command,
	$warning, $critical, 
	%warnval, %critval,
	%channels,
	$sock,
	$key,
	$s,
	$i,
);
my $stop = 0;
my $port = 5038;
my $exitcode = 0;
my $cause = "";

sub warning {
	$s = shift;
	$s =~ s/[\r\n]//g;
	print "WARNING: $s\n" if ($verbose);
	exit(1);
}

sub error {
	$s = shift;
	$s =~ s/[\r\n]//g;
	print "ERROR: $s\n" if ($verbose);
	exit(2);
}

sub unknown {
	$s = shift;
	$s =~ s/[\r\n]//g;
	print "UNKNOWN: $s\n" if ($verbose);
	exit(3);
}

sub syntax {
	$s = shift;
	unless ($s =~ m/Help:/) {
		$s = "Error: (".$s.")" or $s = 'Unknown';
	}
	print "$s\n" unless ($help);
	print "Syntax: $0 -h <host> -u <username> -p <password> [-cwv]\n";
	print "* --username -u       Username\n";
	print "* --password -p       Password\n";
	print "* --host -h           Host\n";
	print "  --port -P n         Port (if not using $port)\n";
	print "  --chan1 -1 xxx      Display channel xxx as 1.\n";
	print "  --chan2 -2 xxx      Display channel xxx as 2.\n";
	print "  --verbose -v        Verbose\n";
	print "  --help -H           This help\n";
	exit(3);
}

Getopt::Long::Configure('bundling');
GetOptions
	("p=s"        => \$password, "password=s" => \$password,
	 "u=s"        => \$username, "username=s" => \$username,
	 "h=s"        => \$host,     "host=s"     => \$host,
	 "P=s"        => \$port,     "port=s"     => \$port,
	 "H"          => \$help,     "help"       => \$help,
	 "v"          => \$verbose,  "verbose"    => \$verbose,
	 "chan1=s"    => \$chan1,    "1=s"        => \$chan1,
	 "chan2=s"    => \$chan2,    "2=s"        => \$chan2);

syntax("Help:") if ($help);
syntax("Missing username") unless (defined($username));
syntax("Missing password") unless (defined($password));
syntax("Missing host") unless (defined($host));
syntax("Missing channels") if (!defined($chan1) or !defined($chan2));
if (defined($warning)) {
	foreach $s (split(/,/, $warning)) {
		syntax("Warning value given, $s, is invalid")
			unless ($s =~ /^(\w+)=(\d+)$/);
		$warnval{$1} = $2;
		print "Clear to give WARNING after $2 connections on $1\n" if ($verbose);
	}
}
if (defined($critical)) {
	foreach $s (split(/,/, $critical)) {
		syntax("Critical value given, $s, is invalid")
			unless ($s =~ /^(\w+)=(\d+)$/);
		$critval{$1} = $2;
		print "Clear to give CRITICAL after $2 connections on $1\n" if ($verbose);
	}
}

unless ($sock = IO::Socket::INET->new(PeerAddr => $host, PeerPort => $port, Proto => 'tcp')) {
	print("Could not connect to asterisk server ".$host.":".$port."\n") if ($verbose);
	exit(2);
}
$version = <$sock>;
print $version if ($verbose);

print $sock "Action: Login\r\nUsername: $username\r\nSecret: $password\r\nEvents: off\r\n\r\n";
print "Action: Login\r\nUsername: $username\r\nSecret: $password\r\n\r\n" if ($verbose);
$response = <$sock>;
$message = <$sock>;
$s = <$sock>;
print $response.$message if ($verbose);
print $s if ($verbose);

exit(1) unless ($response =~ m/^Response:\s+(.*)$/i);
exit(1) unless ($1 =~ m/Success/i);

print $sock "Action: Status\r\n\r\n";
print "Action: Status\r\n\r\n" if ($verbose);

$response = <$sock>;
$message = <$sock>;
print $response.$message if ($verbose);

&unknown("Unknown answer $response (wanted Response: something)") unless ($response =~ m/^Response:\s+(.*)$/i);
&unknown("$response didn't say Success") unless ($1 =~ m/Success/i);
&unknown("Unknown answer $response (wanted Message: something)") unless ($message =~ m/^Message:\s+(.*)$/i);
&unknown("didn't understand message $message") unless ($1 =~ m/Channel status will follow/i);

$stop=0;
while (($stop == 0) && ($line = <$sock>)) {
	print "$line" if ($verbose);
	if ($line =~ m/Channel:\s+(\w+)\//) {
		$channels{$1}++;
		print "Found $1 channel\n" if ($verbose);
	}
	if ($line =~ m/Event:\s*StatusComplete/i) {
		$stop++;
	}
}

# Log out
print $sock "Action: Logoff\r\n\r\n";

undef($s);

for ($i=0;$i<2;$i++) {
	if (defined($channels{$chan1})) {
		print $channels{$chan1} . "\n";
	} else {
		print "0\n";
	}
	if (defined($channels{$chan2})) {
		print $channels{$chan2} . "\n";
	} else {
		print "0\n";
	}
}
