###########################################################################
# package Net::SIP::Blocker
###########################################################################

use strict;
use warnings;


package Net::SIP::Blocker;

use fields qw( dispatcher block );
use Carp 'croak';
use Net::SIP::Debug;


###########################################################################
# creates new Blocker object
# Args: ($class,%args)
#   %args
#     block: \%hash where the blocked method is the key and its value
#       is a number with three digits with optional message
#       e.g. { 'SUBSCRIBE' => 405 }
#     dispatcher: the Net::SIP::Dispatcher object
# Returns: $self
###########################################################################
sub new {
    my ($class,%args) = @_;
    my $self = fields::new( $class );

    my $map = delete $args{block}
	or croak("no mapping between method and code");
    while (my ($method,$code) = each %$map) {
	$method = uc($method);
	($code, my $msg) = $code =~m{^(\d\d\d)(?:\s+(.+))?$} or
	    croak("block code for $method must be DDD [text]");
	$self->{block}{$method} = defined($msg) ? [$code,$msg]:[$code];
    }

    $self->{dispatcher} = delete $args{dispatcher}
	or croak('no dispatcher given');

    return $self;
}


###########################################################################
# Blocks methods not wanted and sends a response back over the same leg
# with the Error-Message of the block_code
# Args: ($self,$packet,$leg,$from)
#   args as usual for sub receive
# Returns: block_code | NONE
###########################################################################
sub receive {
    my Net::SIP::Blocker $self = shift;
    my ($packet,$leg,$from) = @_;

    $packet->is_request or return;

    my $method = $packet->method;
    if ( $method eq 'ACK' and my $block = $self->{block}{INVITE} ) {
	$self->{dispatcher}->cancel_delivery($packet->tid);
	return $block->[0];
    }

    my $block = $self->{block}{$method} or return;

    DEBUG( 10,"block $method with code @$block" );
    $self->{dispatcher}->deliver(
	$packet->create_response(@$block),
	leg => $leg,
	dst_addr => $from
    );
    return $block->[0]
}

1;
