AnyEvent-SIP
view release on metacpan or search on metacpan
# which calls AnyEvent's instead
$ua->loop( 1, \$stopvar );
COMPATIBILITY
Net::SIP requires dispatchers (event loops) to check their stopvars
(condition variables) every single iteration of the loop. In my opinion,
it's a wasteful and heavy operation. When it comes to loops like EV,
they run a lot of cycles, and it's not very effecient and causes heavy
load.
To avoid that, the default mode for AnyEvent::SIP is to set up a timer
to check the condition variables. Default interval is: 0.2 seconds.
To configure this, you can set up the interval on import:
use AnyEvent::SIP stopvar_interval => 0.1;
...
If you want to keep AnyEvent::SIP completely compatible with the
Net::SIP requirement (which fixes at least one bugfix test I haven't
found out why yet), you can add the compat option on import;
lib/AnyEvent/SIP.pm view on Meta::CPAN
# which calls AnyEvent's instead
$ua->loop( 1, \$stopvar );
=head1 COMPATIBILITY
L<Net::SIP> requires dispatchers (event loops) to check their stopvars
(condition variables) every single iteration of the loop. In my opinion, it's
a wasteful and heavy operation. When it comes to loops like L<EV>, they run
a B<lot> of cycles, and it's not very effecient and causes heavy load.
To avoid that, the default mode for L<AnyEvent::SIP> is to set up a timer
to check the condition variables. Default interval is: B<0.2> seconds.
To configure this, you can set up the interval on import:
use AnyEvent::SIP stopvar_interval => 0.1;
...
If you want to keep AnyEvent::SIP completely compatible with the L<Net::SIP>
requirement (which fixes at least one bugfix test I haven't found out why yet),
you can add the compat option on import;
lib/Net/SIP/Dispatcher/AnyEvent.pm view on Meta::CPAN
}
sub delFD {
my $self = shift;
my $fh = shift;
my $fn = fileno $fh or return;
delete $self->{'_fd_watchers'}{$fn};
}
sub add_timer {
my $self = shift;
my ( $when, $cb_data, $repeat, $name ) = @_;
defined $repeat or $repeat = 0;
# is $when epoch or relative?
if ( $when >= 3600*24*365 ) {
$when = AE::now - $when;
}
return Net::SIP::Dispatcher::AnyEvent::Timer->new(
lib/Net/SIP/Dispatcher/AnyEvent.pm view on Meta::CPAN
sub looptime { AE::now }
sub loop {
my $self = shift;
my ( $timeout, @stopvar ) = @_;
$self->{'_stopvar'} = \@stopvar;
if ( ! $self->{'_net_sip_compat'} and @stopvar ) {
# set up a timer to check stopvars
$self->{'_stopvar_timer'} = AE::timer 0, $self->{'_ae_interval'}, sub {
foreach my $var (@stopvar) {
if ( ${$var} ) {
delete $self->{'_stopvar_timer'};
delete $self->{'_stopvar'};
$self->{'_cv'}->send;
}
}
}
}
if ($timeout) {
my $timer; $timer = AE::timer $timeout, 0, sub {
undef $timer;
$self->{'_cv'}->send;
};
}
$self->{'_cv'}->recv;
# clean up, prepare for another round
$self->{'_cv'} = AE::cv;
}
lib/Net/SIP/Dispatcher/AnyEvent.pm view on Meta::CPAN
Condition variables to be checked for stopping the loop.
=head2 _cv
Main condition variable allowing for looping.
=head2 _fd_watchers
All the watched file descriptors.
=head2 _stopvar_timer
Timer holding stopvar checking. Only for default non-compatible mode.
=head1 METHODS
=head2 new
The object constructor. It creates a default CondVar in C<_cv> hash key,
and sets an aggressive idle CondVar in the C<_idle> hash key, which checks
the stopvars every loop cycle.
=head2 addFD($fd, $cb_data, [$name])
Add a file descriptor to watch input for, and a callback to run when it's ready
to be read.
=head2 delFD($fd)
Delete the watched file descriptor.
=head2 add_timer($when, $cb_data, [$repeat], [$name])
Create a timer to run a callback at a certain point in time. If the time is
considerably far (3,600 * 24 * 365 and up), it's a specific point in
time. Otherwise, it's a number of seconds from now.
The C<repeat> option is an optional interval for the timer.
=head2 looptime
Provide the event loop time.
=head2 loop($timeout, [\@stopvars])
Run the event loop and wait for all events to finish (whether by timeout or
stopvars becoming true).
lib/Net/SIP/Dispatcher/AnyEvent/Timer.pm view on Meta::CPAN
use strict;
use warnings;
package Net::SIP::Dispatcher::AnyEvent::Timer;
{
$Net::SIP::Dispatcher::AnyEvent::Timer::VERSION = '0.002';
}
# ABSTRACT: A timer object for Net::SIP::Dispatcher::AnyEvent
use AnyEvent;
use Net::SIP::Util 'invoke_callback';
sub new {
my $class = shift;
my ( $name, $when, $repeat, $cb ) = @_;
my $self = bless {}, $class;
$self->{'timer'} = AE::timer $when, $repeat, sub {
invoke_callback( $cb, $self );
};
return $self;
}
sub cancel {
my $self = shift;
delete $self->{'timer'};
}
1;
=pod
=head1 NAME
Net::SIP::Dispatcher::AnyEvent::Timer - A timer object for Net::SIP::Dispatcher::AnyEvent
=head1 VERSION
version 0.002
=head1 DESCRIPTION
The timer object L<Net::SIP::Dispatcher::AnyEvent> creates when asked for a
new timer.
=head1 INTERNAL ATTRIBUTES
These attributes have no accessors, they are saved as internal keys.
=head2 timer
The actual timer object
=head1 METHODS
=head2 new($name, $when, $repeat, $cb_data)
A constructor creating the new timer. You set when to start, the callback and
how often to repeat.
=head2 cancel
Cancel the timer.
=head1 AUTHOR
Sawyer X <xsawyerx@cpan.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2013 by Sawyer X.
This is free software; you can redistribute it and/or modify it under
t/02_listen_and_invite.t view on Meta::CPAN
diag( 'got ringing' );
$ringing ++
}
}
);
ok( $ringing,'got ringing' );
ok( ! $uac->error, 'no error on UAC' );
ok( $call, 'Call established' );
my $ran_ae;
my $t = AE::timer 0.01, 0, sub { $ran_ae++ };
$call->loop(1);
ok( $ran_ae, 'Ran AnyEvent timer' );
my $stop;
$call->bye( cb_final => \$stop );
$call->loop( \$stop,10 );
ok( $stop, 'UAS down' );
}
###############################################
# UAS
###############################################
t/11_invite_timeout.t view on Meta::CPAN
sub uas {
my ($sock,$pipe) = @_;
Net::SIP::Debug->set_prefix( "DEBUG(uas):" );
my $uas = Net::SIP::Simple->new(
domain => 'example.com',
leg => $sock
) || die $!;
print $pipe "UAS created\n";
my $timer;
my $got_cancel;
my $my_receive = sub {
my ($self,$endpoint,$ctx,$error,$code,$packet,$leg,$from) = @_;
if ( $packet->is_request && $packet->method eq 'INVITE' ) {
# just ring
my $ring = $packet->create_response( 180,'Ringing' );
$timer ||= $endpoint->{dispatcher}->add_timer( 1,
sub { $endpoint->new_response( $ctx,$ring,$leg,$from ) },
1 );
return;
}
if ( $timer && $packet->is_request && $packet->method eq 'CANCEL' ) {
$timer->cancel;
$got_cancel =1;
}
goto &Net::SIP::Simple::Call::receive;
};
# Listen
$uas->listen( cb_create => sub { return $my_receive } );
# notify UAC process that I'm listening
print $pipe "UAS ready\n";
t/anyevent.t view on Meta::CPAN
}
);
$cv->recv;
ok( $ringing,'got ringing' );
ok( ! $uac->error, 'no error on UAC' );
ok( $call, 'Call established' );
$cv = AE::cv;
my $timer = AE::timer 1, 0, sub { $cv->send };
$cv->recv;
my $stop = 0;
$cv = AE::cv;
$timer = AE::timer 10, 0, sub { $cv->sned };
$call->bye( cb_final => sub { $stop++; $cv->send } );
$cv->recv;
ok( $stop, 'UAS down' );
}
###############################################
# UAS
###############################################
( run in 1.586 second using v1.01-cache-2.11-cpan-49f99fa48dc )