The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/perl

#Author: Ryan Bullock
#Version: 0.1
#Description: This provided a very simple event proxy for the asterisk manager interface.

use strict;
use warnings;
use AnyEvent::Impl::Perl;
use AnyEvent;
use AnyEvent::Handle;
use AnyEvent::Socket;
use Asterisk::AMI;

#Port to listen on
my $port = 5039;

#Delimiters
my $EOL = "\015\012";

my $EOR = $EOL;

#Keep a list of clients
my %clients;

#Connect to asterisk
my $astman = Asterisk::AMI->new(PeerAddr => '127.0.0.1',
				Username => 'admin',
				Secret	=> 'supersecret',
				Events	=> 'on', #Give us something to proxy
				Timeout => 3, #Default timeout for all operations, 3 seconds
				Handlers => { default => \&proxy_event }, #Install default handler
				Keepalive => 60, #Send a keepalive every minute
				on_error => sub { print "Error occured on socket\r\n"; exit; },
				on_timeout => sub { print "Connection to asterisk timed out\r\n"; exit; }
			);

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

#Handler for events
sub proxy_event {
	my ($asterisk, $event) = @_;

	#Event string to build and proxy
	my $pevent;

	#Build the proxied event string
	#For now pretend we like we are asterisk and format as such

	#String from {'DATA'}
	my $dstring;

	#DATA in events are usually lines without values
	#something like 'AppData:' but nothing in the value
	#We don't have to send them, but just to be 'compatible' we will
	foreach my $data (@{$event->{'DATA'}}) {
		$dstring .= $data . $EOL;
	}

	$dstring .= $EOR;

	delete $event->{'DATA'};

	while (my ($key, $value) = each(%{$event})) {
		$pevent .= $key . ': ' . $value . $EOL;
	}

	#Stick the DATA fields at the end
	$pevent .= $dstring;

	#Send it to all the clients
	foreach my $handle (values %clients) {
		$handle->push_write($pevent);
	}

	return 1;
}

#Remove a client if they d/c or error
sub remove_client {
	delete $clients{$_[0]->fh};
	$_[0]->destroy;
	return 1;
}

#Handles new connections
sub new_client {
	my ($fh, $host, $port) = @_;

	#Create an AnyEvent handler for the client
	my $handle = new AnyEvent::Handle(	fh => $fh,
						on_error => \&remove_client,
						on_eof => \&remove_client
						);

	#Discard client input
	$handle->push_read( line => sub { return; });

	#Send a greeting
	$handle->push_write('Connected to event proxy.' . "\r\n");

	$clients{$handle} = $handle;
}

#Our server to accept connections
tcp_server undef, $port, \&new_client;

#Start our server
print "Starting Event Proxy\r\n";
AnyEvent::Impl::Perl::loop;