#!/usr/bin/perl

use strict;
use warnings;
use Config::Simple;
use Asterisk::AMI;

my $ConfigFile = '/etc/ntools/zabbix/asterisk.conf';
my %Config = ();
Config::Simple->import_from("$ConfigFile", \%Config) || die "Can't open config $ConfigFile\n";

my $astman = Asterisk::AMI->new(PeerAddr => $Config{'default.hostname'},
	PeerPort => $Config{'default.port'},
	Username => $Config{'default.username'},
	Secret => $Config{'default.secret'}
);

die "Unable to connect to asterisk" unless ($astman);

sub GetMonPeersList {
	my $peers = [];
	foreach my $peer (@{&GetPeersList}) {
		my $action = $astman->send_action({ Action => 'Command',
			Command => 'sip show peer '.$peer
		});

		my $response = $astman->get_response($action);
		foreach (@{$response->{'CMD'}}) {
			if (/Status\s+:\s+([^:]+)$/) {
				my $status = $1;
				push @{$peers}, $peer if ($status ne 'Unmonitored');
			};
		};
	};
	return $peers;
}

sub GetPeersList {
	my $action = $astman->send_action({ Action => 'Command',
		Command => 'sip show objects'
	});
	my $peers = [];
	my $response = $astman->get_response($action);
	foreach (@{$response->{'CMD'}}) {
		last if /Peer objects by IP/;
		next unless /^name:\s([^\s]+)$/;
		push @{$peers}, $1;
	};
	return $peers;
};

sub GetRegistryList {
	my $action = $astman->send_action({ Action => 'Command',
		Command => 'sip show registry'
	});
	my $regs = [];
	my $start = 0;
	my $response = $astman->get_response($action);
	shift @{$response->{'CMD'}};
	foreach (@{$response->{'CMD'}}) {
		/^([^\s]+)\s/;
		push @{$regs}, $1;
	};
	pop @{$regs};
	return $regs;
};

sub DiscoveryMonPeers {
	my @peers = @{&GetMonPeersList};
	print '{"data":[';
	if ($#peers > 0) {
		print '{"{#PNAME}":"';
		print join '"},{"{#PNAME}":"', @peers;
		print '"}';	
	};
	print ']}';	
	exit 0;
}

sub trim {
	my $s = shift;
	$s =~ s/^\s+|\s+$//g;
	return $s 
};

sub ltrim {
	my $s = shift;
	$s =~ s/^\s+//;
	return $s 
};

sub rtrim {
	my $s = shift;
	$s =~ s/\s+$//;
	return $s 
};

sub DiscoveryRegistry {
	my $action = $astman->send_action({ Action => 'Command',
		Command => 'sip show registry'
	});
	my $response = $astman->get_response($action);
	shift @{$response->{'CMD'}};
	pop @{$response->{'CMD'}};
	print '{"data":[';
	my $first = 1;
	foreach (@{$response->{'CMD'}}) {
		my ($host, $dnsmgr, $username, $refresh, $tmp) = split (/\s+/, $_, 5);
		if ($first) {
			$first = 0;
		} else {
			print ",";
		}
		my $state = '';
		if ($tmp =~ /^Registered/) {
			$state = 'Registered';
		} elsif ($tmp =~ /^Request Sent/) {
			$state = 'Request Sent';
		} elsif ($tmp =~ /^No Authentication/) {
			$state = 'No Authentication';
		};
		print '{"{#RNAME}":"';
		$username =~ tr/@/-/;
		print $host.':'.$username;
		print '",';	
		print '"{#RSTATE}":"';
		print $state;
		print '"}';	
	};
	print ']}';	
	exit 0;
}

sub GetRegistryState {
	my $name = shift; 
	my $action = $astman->send_action({ Action => 'Command',
		Command => 'sip show registry'
	});
	my $response = $astman->get_response($action);
	shift @{$response->{'CMD'}};
	pop @{$response->{'CMD'}};
	foreach (@{$response->{'CMD'}}) {
		my ($host, $dnsmgr, $username, $refresh, $tmp) = split (/\s+/, $_, 5);

		my $state = '';
		my $regtime = '';
		if ($tmp =~ /^Registered/) {
			$state = 'Registered';
			$regtime = $1 if $tmp =~ /^Registered\s+(.+)$/;
		} elsif ($tmp =~ /^Request Sent/) {
			$state = 'Request Sent';
		} elsif ($tmp =~ /^No Authentication/) {
			$state = 'No Authentication';
		};

		my $rname = $host.':'.$username;
		$rname =~ tr/@/-/;

		next if $rname ne $name;
		print $state;
	};
	exit 0;
}

sub GetPeerStatus {
	my $peer = shift; 
	my $action = $astman->send_action({ Action => 'Command',
		Command => 'sip show peer '.$peer
	});

	my $response = $astman->get_response($action);
	foreach (@{$response->{'CMD'}}) {
		if (/Status\s+:\s+([^:]+)$/) {
			my $status = $1;
			if ($status =~/(\d+)/) {
				print "$1";
				exit 0;
			} else {
				print "0";
				exit 0;
			}
		};
	};
}

sub GetCalls {
	my $action = $astman->send_action({ Action => 'Command',
		Command => 'core show channels'
	});

	my $response = $astman->get_response($action);
	foreach (@{$response->{'CMD'}}) {
		if (/^(\d+)\s+calls processed/) {
			print $1;
		};
	};
	exit 0;
}

sub GetActiveCalls {
	my $action = $astman->send_action({ Action => 'Command',
		Command => 'core show channels'
	});

	my $response = $astman->get_response($action);
	foreach (@{$response->{'CMD'}}) {
		if (/^(\d+)\s.+active call/) {
			print $1;
		};
	};
	exit 0;
}

sub GetActiveChannels {
	my $action = $astman->send_action({ Action => 'Command',
		Command => 'core show channels'
	});

	my $response = $astman->get_response($action);
	foreach (@{$response->{'CMD'}}) {
		if (/^(\d+)\s+active channels/) {
			print $1;
		};
	};
	exit 0;
}

sub GetPeersCount {
	my $action = $astman->send_action({ Action => 'Command',
		Command => 'sip show peers'
	});

	my $response = $astman->get_response($action);
	foreach (@{$response->{'CMD'}}) {
		if (/^(\d+)\s+sip peers/) {
			print $1;
		};
	};
	exit 0;
}

sub GetOnMonPeersCount {
	my $action = $astman->send_action({ Action => 'Command',
		Command => 'sip show peers'
	});

	my $response = $astman->get_response($action);
	foreach (@{$response->{'CMD'}}) {
		if (/sip peers[^\d]+(\d+)[^\d]+(\d+)[^\d]+(\d+)[^\d]+(\d+)/) {
			print $1;
		};
	};
	exit 0;
}

sub GetOffMonPeersCount {
	my $action = $astman->send_action({ Action => 'Command',
		Command => 'sip show peers'
	});

	my $response = $astman->get_response($action);
	foreach (@{$response->{'CMD'}}) {
		if (/sip peers[^\d]+(\d+)[^\d]+(\d+)[^\d]+(\d+)[^\d]+(\d+)/) {
			print $2;
		};
	};
	exit 0;
}

sub GetOnUnmonPeersCount {
	my $action = $astman->send_action({ Action => 'Command',
		Command => 'sip show peers'
	});

	my $response = $astman->get_response($action);
	foreach (@{$response->{'CMD'}}) {
		if (/sip peers[^\d]+(\d+)[^\d]+(\d+)[^\d]+(\d+)[^\d]+(\d+)/) {
			print $3;
		};
	};
	exit 0;
}

sub GetOffUnmonPeersCount {
	my $action = $astman->send_action({ Action => 'Command',
		Command => 'sip show peers'
	});

	my $response = $astman->get_response($action);
	foreach (@{$response->{'CMD'}}) {
		if (/sip peers[^\d]+(\d+)[^\d]+(\d+)[^\d]+(\d+)[^\d]+(\d+)/) {
			print $4;
		};
	};
	exit 0;
}

sub GetVersion {
	my $action = $astman->send_action({ Action => 'Command',
		Command => 'core show settings'
	});

	my $response = $astman->get_response($action);
	foreach (@{$response->{'CMD'}}) {
		if (/Version:\s+([^\s]+)/) {
			print $1;
		};
	};
	exit 0;
}

sub GetUptime {
	my $action = $astman->send_action({ Action => 'Command',
		Command => 'core show uptime seconds'
	});

	my $response = $astman->get_response($action);
	foreach (@{$response->{'CMD'}}) {
		if (/uptime:\s+([^\s]+)/) {
			print $1;
		};
	};
	exit 0;
}

sub GetReloadTime {
	my $action = $astman->send_action({ Action => 'Command',
		Command => 'core show uptime seconds'
	});

	my $response = $astman->get_response($action);
	foreach (@{$response->{'CMD'}}) {
		if (/reload:\s+([^\s]+)/) {
			print $1;
		};
	};
	exit 0;
}

sub PrintUsage {
	print "Usage: $0 command\n";
  print " Commands available:\n";
  print "   discovery-mon-peers\n";
  print "   discovery-registry\n";
  print "   <PeerName> get-peer-status\n";
  print "   <PeerName> get-registry-state\n";
  print "   get-calls\n";
  print "   get-active-calls\n";
  print "   get-active-channels\n";
  print "   get-peers-count\n";
  print "   get-on-mon-peers-count\n";
  print "   get-off-mon-peers-count\n";
  print "   get-on-unmon-peers-count\n";
  print "   get-off-unmon-peers-count\n";
  print "   get-version\n";
  print "   get-uptime\n";
  print "   get-reload-time\n";
  exit 1;
}

&PrintUsage unless (defined $ARGV[0]);

&DiscoveryMonPeers if ($ARGV[0] eq 'discovery-mon-peers');
&DiscoveryRegistry if ($ARGV[0] eq 'discovery-registry');

&GetCalls if ($ARGV[0] eq 'get-calls');
&GetActiveCalls if ($ARGV[0] eq 'get-active-calls');
&GetActiveChannels if ($ARGV[0] eq 'get-active-channels');
&GetPeersCount if ($ARGV[0] eq 'get-peers-count');
&GetOnMonPeersCount if ($ARGV[0] eq 'get-on-mon-peers-count');
&GetOffMonPeersCount if ($ARGV[0] eq 'get-off-mon-peers-count');
&GetOnUnmonPeersCount if ($ARGV[0] eq 'get-on-unmon-peers-count');
&GetOffUnmonPeersCount if ($ARGV[0] eq 'get-off-unmon-peers-count');
&GetVersion if ($ARGV[0] eq 'get-version');
&GetUptime if ($ARGV[0] eq 'get-uptime');
&GetReloadTime if ($ARGV[0] eq 'get-reload-time');

&PrintUsage unless (defined $ARGV[1]);
&GetPeerStatus($ARGV[0]) if ($ARGV[1] eq 'get-peer-status');
&GetRegistryState($ARGV[0]) if ($ARGV[1] eq 'get-registry-state');
&PrintUsage;

