Asterisk-AMI

 view release on metacpan or  search on metacpan

lib/Asterisk/AMI.pm  view on Meta::CPAN

#Register warnings
use warnings::register;

use strict;
use warnings;

use AnyEvent;
use AnyEvent::Handle;
use AnyEvent::Socket;
use Digest::MD5;
use Scalar::Util qw/weaken/;
use Carp qw/carp/;

#Duh
use version 0.77; our $VERSION = version->declare("v0.2.8");

#Used for storing events while reading command responses Events are stored as hashes in the array Example 
#$self->{EVETNBUFFER}->{'Event'} = Something

#Buffer for holding action responses and data
# Structure: $self->{RESPONSEBUFFER}->{'ActionID'}->{'Response'}        = (Success|Failure|Follows|Goodbye|Pong|Etc..)        

lib/Asterisk/AMI.pm  view on Meta::CPAN

                #and don't mess with the handlers
                } elsif (lc($self->{CONFIG}->{EVENTS}) !~ /on|call/x) {
                        $self->{CONFIG}->{EVENTS} .= ',call';
                }
        }

        #Initialize the seq number
        $self->{idseq} = 1;

        #Weaken reference for use in anonsub
        weaken($self);

        #Set keepalive
        $self->{CONFIG}->{KEEPALIVE} = AE::timer($self->{CONFIG}->{KEEPALIVE}, $self->{CONFIG}->{KEEPALIVE}, sub { $self->_send_keepalive }) if ($self->{CONFIG}->{KEEPALIVE});
        
        return 1;
}

#Handles connection failures (includes login failure);
sub _on_connect_err {

lib/Asterisk/AMI.pm  view on Meta::CPAN


        my ($self, $fh, $line) = @_;

        if ($line =~ /^Asterisk\ Call\ Manager\/([0-9]\.[0-9])$/ox) {
                $self->{AMIVER} = $1;
        } else {
                warnings::warnif('Asterisk::AMI', "Unknown Protocol/AMI Version from $self->{CONFIG}->{PEERADDR}:$self->{CONFIG}->{PEERPORT}");
        }

        #Weak reference for us in anonysub
        weaken($self);

        $self->{handle}->push_read( 'Asterisk::AMI' => sub { $self->_handle_packet(@_); } );

        return 1;
}

#Connects to the AMI Returns 1 on success, 0 on failure
sub _connect {
        my ($self) = @_;

        #Weaken ref for use in anonysub
        weaken($self);

        #Build a hash of our anyevent::handle options
        my %hdl = (     connect => [$self->{CONFIG}->{PEERADDR} => $self->{CONFIG}->{PEERPORT}],
                        on_connect_err => sub { $self->_on_connect_err($_[1]); },
                        on_error => sub { $self->_on_error($_[2]) },
                        on_eof => sub { $self->_on_disconnect; },
                        on_connect => sub { $self->{handle}->push_read( line => sub { $self->_on_connect(@_); } ); });

        #TLS stuff
        $hdl{'tls'} = 'connect' if ($self->{CONFIG}->{USESSL});

lib/Asterisk/AMI.pm  view on Meta::CPAN

                delete $self->{EXPECTED}->{$id};
                return $resp;
        }

        #Don't Have it, wait for it Install some handlers and use a CV to simulate blocking
        my $process = AE::cv;

        $self->{CALLBACKS}->{$id}->{'cb'} = sub { $process->send($_[1]) };
        $timeout = $self->{CONFIG}->{TIMEOUT} unless (defined $timeout);

        #Should not need to weaken here because this is a blocking call Only outcomes can be error, timeout, or 
        #complete, all of which will finish the cb and clear the reference weaken($self)

        if ($timeout) {
                $self->{CALLBACKS}->{$id}->{'timeout'} = sub {
                                my $response = $self->{'RESPONSEBUFFER'}->{$id};
                                delete $self->{RESPONSEBUFFER}->{$id};
                                delete $self->{CALLBACKS}->{$id};
                                delete $self->{EXPECTED}->{$id};
                                $process->send($response);
                        };

lib/Asterisk/AMI.pm  view on Meta::CPAN

                $self->{handle}->push_write($action);
        } else {
                $self->{PRELOGIN}->{$id} = $action;
        }

        $self->{RESPONSEBUFFER}->{$id}->{'COMPLETED'} = 0;
        $self->{RESPONSEBUFFER}->{$id}->{'GOOD'} = 0;
        $self->{EXPECTED}->{$id} = 1;

        #Weaken ref of use in anonsub
        weaken($self);

        #Set default timeout if needed
        $timeout = $self->{CONFIG}->{TIMEOUT} unless (defined $timeout);

        #Setup callback
        if (defined $callback) {
                #Set callback if defined
                $self->{CALLBACKS}->{$id}->{'cb'} = $callback;
                #Variable to return with Callback
                $self->{CALLBACKS}->{$id}->{'store'} = $store;

lib/Asterisk/AMI.pm  view on Meta::CPAN

        }

        return $self->_logged_in($resp);   
}

#Non-blocking login
sub _login_noblock {
        my ($self, $action, $challenge, $timeout) = @_;

        #Weaken ref for use in anonsub
        weaken($self);

        #Callback for login action
        my $login_cb = sub { $self->_logged_in($_[1]) };

        #Do a md5 challenge
        if (%{$challenge}) {
                #Create callbacks for the challenge
                 my $challenge_cb = sub {
                                if ($_[1]->{'GOOD'}) {
                                        my $md5 = Digest::MD5->new();

lib/Asterisk/AMI.pm  view on Meta::CPAN

#Check whether there was an error on the socket
sub error {
        my ($self) = @_;
        return $self->{SOCKERR};
}

#Sends a keep alive
sub _send_keepalive {
        my ($self) = @_;
        #Weaken ref for use in anonysub
        weaken($self);
        my $cb = sub { 
                        unless ($_[1]->{'GOOD'}) {
                                $self->_on_timeout("Asterisk failed to respond to keepalive - $self->{CONFIG}->{PEERADDR}:$self->{CONFIG}->{PEERPORT}");
                        };
                 };

        my $timeout = $self->{CONFIG}->{TIMEOUT} || 5;
        
        return $self->send_action({ Action => 'Ping' }, $cb, $timeout);
}



( run in 0.345 second using v1.01-cache-2.11-cpan-65fba6d93b7 )