AnyEvent-SIP

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN

        # 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 )