Commit 608095f1 authored by Steffen Ullrich's avatar Steffen Ullrich

fix tracking of error response code for INVITE in case multiple INVITEs are in process in parallel

parent 4943bd7b
......@@ -541,13 +541,13 @@ sub receive {
$param->{leg} ||= $leg;
$self->_setup_local_rtp_socks;
invoke_callback($param->{cb_invite},$self,$packet);
my $resp = invoke_callback($param->{cb_invite},$self,$packet);
# send 200 OK with sdp body
my $response = $packet->create_response(
'200','OK',{},$param->{sdp} );
DEBUG( 100,'created response '.$response->as_string );
$self->{endpoint}->new_response( $ctx,$response,$leg,$from );
# by default send 200 OK with sdp body
$resp = $packet->create_response('200','OK',{},$param->{sdp})
if ! $resp || ! UNIVERSAL::isa($resp,'Net::SIP::Packet');
DEBUG( 100,'created response '.$resp->as_string );
$self->{endpoint}->new_response( $ctx,$resp,$leg,$from );
} elsif ( $method eq 'ACK' ) {
$self->rtp_cleanup; # close last RTP session
......
......@@ -163,7 +163,9 @@ Callback usable by B<invoke_callback> in L<Net::SIP::Util> which will be
invoked, when it received an INVITE request
Callback will be invoked with C<< ( SELF, REQUEST ) >> where REQUEST
is the L<Net::SIP::Request> packet for the INVITE.
is the L<Net::SIP::Request> packet for the INVITE. If it returns a
Net::SIP::Packet this will be used as response, otherwise a default response
with code 200 will be created.
=item cb_dtmf
......
......@@ -50,6 +50,7 @@ sub new {
};
$self->{nathelper} = delete $args{nathelper};
$self->{force_rewrite} = delete $args{force_rewrite};
$self->{respcode} = [ {},{} ];
return $self;
}
......@@ -254,7 +255,6 @@ sub receive {
}
}
$self->{respcode} = $packet->code;
__forward_response( $self, \%entry );
} else {
......@@ -642,6 +642,11 @@ sub do_nat {
: ( undef,$packet )
;
my $method = $request ? $request->method : '';
my $track_resp_code;
if ($response and $response->method eq 'INVITE') {
my $code = $response->code;
$track_resp_code = $code if $code>=400;
}
# NAT for anything with SDP body
# activation and close of session will be done on ACK|CANCEL|BYE
......@@ -650,7 +655,7 @@ sub do_nat {
or $method eq 'CANCEL'
or $method eq 'BYE' ) {
DEBUG( 100, "no NAT because no SDP body and method is $method" );
return;
return if ! $track_resp_code;
}
......@@ -694,6 +699,18 @@ sub do_nat {
or return [ 0,'no CSEQ in packet' ];
my $callid = $packet->callid;
if ($track_resp_code) {
my $rc = $self->{respcode}[0];
if (keys(%$rc)>5000) {
# expire entries
$self->{respcode}[1] = $rc;
$rc = $self->{respcode}[0] = {};
}
$rc->{$callid,$cseq,$idfrom,$idto} = $track_resp_code;
# no NAT to do, we just needed to track the response code
return;
}
# CANCEL|BYE will be handled first to close session
# no NAT will be done, even if the packet contains SDP (which makes no sense)
if ( $method eq 'CANCEL' ) {
......@@ -730,7 +747,10 @@ sub do_nat {
if ( ! $nathelper->activate_session( $callid,$cseq,$idfrom,$idto ) ) {
if ( $method eq 'ACK' ) {
if ($self->{respcode} < 400) {
my $code = $self->{respcode}[0]{$callid,$cseq,$idfrom,$idto}
|| $self->{respcode}[1]{$callid,$cseq,$idfrom,$idto}
|| -1;
if ($code < 400) {
DEBUG( 50,"session $callid|$cseq $idfrom -> $idto still incomplete in ACK" );
return [ 0,'incomplete session in ACK' ]
} else {
......
......@@ -104,11 +104,11 @@ sub do_test {
fd_grep_ok( qr{O>.*REQ\(INVITE\) SDP: audio=\S+},1,$proxy ) || die;
fd_grep_ok( qr{I<.*REQ\(INVITE\) SDP: audio=\S+},1,$uas ) || die;
# UAS: reject with error 504 - propagate to uac via proxy
fd_grep_ok( qr{O>.*RSP\(INVITE,504\)},5,$uas) || die;
fd_grep_ok( qr{I<.*RSP\(INVITE,504\)},5,$proxy) || die;
fd_grep_ok( qr{O>.*RSP\(INVITE,504\)},1,$proxy) || die;
fd_grep_ok( qr{I<.*RSP\(INVITE,504\)},1,$uac) || die;
# UAS: reject with error 404 - propagate to uac via proxy
fd_grep_ok( qr{O>.*RSP\(INVITE,404\)},5,$uas) || die;
fd_grep_ok( qr{I<.*RSP\(INVITE,404\)},5,$proxy) || die;
fd_grep_ok( qr{O>.*RSP\(INVITE,404\)},1,$proxy) || die;
fd_grep_ok( qr{I<.*RSP\(INVITE,404\)},1,$uac) || die;
# UAC: reply with ACK to error - propagate to uas via proxy
fd_grep_ok( qr{O>.*REQ\(ACK\)},5,$uac ) || die;
......@@ -153,14 +153,14 @@ sub proxy {
sub uac {
my ($leg,$proxy_uri) = @_;
my $ua = Simple->new(
from => 'me.uac@example.com',
from => '<sip:me.uac@example.com>',
leg => $leg->{leg},
outgoing_proxy => $proxy_uri,
);
print "ready\n";
my $done;
my $call = $ua->invite('you.uas@example.com',
my $call = $ua->invite('<sip:you.uas@example.com>',
cb_final => \$done,
) or die;
$ua->loop(10,\$done);
......@@ -174,19 +174,20 @@ sub uac {
sub uas {
my ($leg) = @_;
my $loop = Dispatcher_Eventloop->new;
my $disp = Dispatcher->new( [ $leg->{leg} ],$loop ) || die $!;
print "UAS created\n";
# Blocking
my $block = Net::SIP::Blocker->new(
block => { 'INVITE' => 504 },
dispatcher => $disp,
my $ua = Simple->new(
from => '<sip:me.uas@example.com>',
leg => $leg->{leg},
);
$disp->set_receiver( $block );
print "ready\n";
$loop->loop(10);
$ua->listen(
cb_invite => sub {
my ($self,$request) = @_;
return $request->create_response('404','unknown',{});
}
);
$ua->loop(10);
}
# --------------------------------------------------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment