You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
rtpengine/t/auto-daemon-tests-t38.pl

801 lines
18 KiB

#!/usr/bin/perl
use strict;
use warnings;
use NGCP::Rtpengine::Test;
use NGCP::Rtpclient::SRTP;
use NGCP::Rtpengine::AutoTest;
use Test::More;
use IPC::Open3;
autotest_start(qw(--config-file=none -t -1 -i 203.0.113.1 -i 2001:db8:4321::1
-n 2223 -c 12345 -f -L 7 -E -u 2222 --jitter-buffer=10))
or die;
my ($sock_a, $sock_b, $port_a, $port_b, $resp, $srtp_ctx_a, $srtp_ctx_b, @ret1, @ret2);
sub fec {
my ($seq_out, $num_ec, $span, $packets) = @_;
my $ec_ents = 0;
my $ec_list = '';
for my $ec_pack (0 .. ($num_ec-1)) {
my $ec_seq = $seq_out - $num_ec * $span + $ec_pack;
last if $ec_seq < 0 || !exists($packets->[$ec_seq]);
my $xor = '';
for my $fec_iter ((0 .. ($span-1))) {
my $fec_seq = $ec_seq + $fec_iter * $num_ec;
my $ecpkt = $packets->[$fec_seq];
ok (defined $ecpkt, "FEC packet $fec_seq exists");
ok (length($ecpkt) < 0x80, 'FEC packet short enough');
$xor ^= $ecpkt;
}
$ec_list .= pack('Ca*', length($xor), $xor);
$ec_ents++;
}
return ($ec_ents, $ec_list);
}
sub t38_gw_test {
my ($testname, $pcm_cmd, $t38_cmd, %opts) = @_;
my ($pcm_pid, $pcm_src, $pcm_sink);
ok($pcm_pid = open3($pcm_sink, $pcm_src, '>&STDERR', $pcm_cmd),
"$testname - spandsp_send_fax_pcm");
unlink('out.tif');
ok (! -e 'out.tif', 'output file does not exists');
my ($t38_pid, $t38_src, $t38_sink);
ok($t38_pid = open3($t38_sink, $t38_src, '>&STDERR', $t38_cmd),
"$testname - spandsp_recv_fax_t38");
my ($buf, $rin);
my $seq = -1;
my $t38_pkt = '';
my $udptl_seq = 0;
my @udptl_ec_in;
my @udptl_ec_out;
my $done = 0;
my $sqo = 1000;
my $tso = 3000;
my $ts = -1;
my $ssrc = -1;
my $rev = $opts{reverse} // 0;
my $pcm_sock = $rev ? $sock_a : $sock_b;
my $pcm_port = $rev ? $port_b : $port_a;
my $t38_sock = $rev ? $sock_b : $sock_a;
my $t38_port = $rev ? $port_a : $port_b;
my $num_ec = $opts{num_ec} // 3;
my $span = $opts{span} // 1;
my $fec = $span > 1;
# speed is controlled by the PCM generator
while (!$done && sysread($pcm_src, $buf = '', 160) == 160) {
# send generated PCM to rtpengine
snd($pcm_sock, $pcm_port, rtp(8, $sqo += 1, $tso += 160, 0x1234, $buf));
# it will also have generated a block of PCM
if ($seq == -1) {
($seq, $ts, $ssrc, $buf) = rcv($pcm_sock, $pcm_port, rtpmre(8 | 0x80, -1, -1, -1, '(' . ("." x 160) . ')'));
if ($opts{seq}) {
is($seq, $opts{seq}, 'initial sequence number');
}
}
else {
($buf) = rcv($pcm_sock, $pcm_port, rtpmre(8, $seq += 1, $ts += 160, $ssrc, '(' . ("." x 160) . ')'));
}
# write it back to our PCM endpoint
is length($buf), 160, 'buf length ok';
ok (syswrite($pcm_sink, $buf), 'PCM writeback');
# read from our local T.38 producer?
$rin = '';
vec($rin, fileno($t38_src), 1) = 1;
while (select(my $rout = $rin, undef, undef, 0) == 1) {
my $ret = sysread($t38_src, $buf = '', 1);
ok (defined($ret), 'T.38 read ok');
if ($ret == 0) {
# EOF
$done = 1;
ok (waitpid($t38_pid, 0), 'T.38 spandsp finished');
undef($t38_pid);
last;
}
$t38_pkt .= $buf;
# complete packet?
my ($seq_out, $len, $pkt) = unpack('SSa*', $t38_pkt);
next unless defined($pkt); # nope
next if length($pkt) < $len; # nope
# extract...
substr($t38_pkt, 0, $len + 4) = '';
substr($pkt, $len) = '';
ok ($len > 0 && $len < 0x80, "local packet $seq_out short enough");
# save for EC
$udptl_ec_out[$seq_out] = $pkt;
# redundancy:
my $ec_method = 0x00;
my $ec_span = '';
my $ec_ents = 0;
my $ec_list = '';
if (!$fec) {
for my $ec_seq (reverse(($seq_out - $num_ec) .. ($seq_out - 1))) {
last if $ec_seq < 0 || !exists($udptl_ec_out[$ec_seq]);
my $ecpkt = $udptl_ec_out[$ec_seq];
ok (length($ecpkt) < 0x80, 'EC packet short enough');
$ec_list .= pack('Ca*', length($ecpkt), $ecpkt);
$ec_ents++;
}
}
else {
$ec_method = 0x80;
$ec_span = pack('CC', 1, $span);
($ec_ents, $ec_list) = fec($seq_out, $num_ec, $span, \@udptl_ec_out);
}
# pack into UDPTL with redundancy
my $udptl = pack('nCa*Ca*Ca*', $seq_out, length($pkt), $pkt, $ec_method,
$ec_span, $ec_ents, $ec_list);
# send
snd($t38_sock, $t38_port, $udptl);
}
# read from our UDPTL source?
$rin = '';
vec($rin, fileno($t38_sock), 1) = 1;
while (select(my $rout = $rin, undef, undef, 0) == 1) {
my ($enc_seq, $len, $pkt) = rcv($t38_sock, $t38_port, qr/^(..)(.)(.*)$/s);
# allow for duplicates, as they're generated in some cases
ok ($enc_seq == $udptl_seq || $enc_seq == $udptl_seq + 1, "UDPTL seq $enc_seq");
$udptl_seq = $enc_seq;
$len = ord($len);
ok ($len > 0 && $len < 0x80, 'remote packet short enough');
# extract...
my $ifp = substr($pkt, 0, $len, '');
ok (length($ifp) == $len, 'length matches');
$udptl_ec_in[$udptl_seq] = $ifp;
my $red = substr($pkt, 0, 1, '');
ok ($red eq ($fec ? "\x80" : "\x00"), 'redundacy method');
if (!$fec) {
my $nec = substr($pkt, 0, 1, '');
ok ($nec eq chr($udptl_seq > 3 ? 3 : $udptl_seq), "num EC packets " . ord($nec));
$nec = ord($nec);
# check EC packets
for my $ec_seq (reverse(($udptl_seq - $nec) .. ($udptl_seq - 1))) {
my $len = substr($pkt, 0, 1, '');
$len = ord($len);
ok ($len > 0 && $len < 0x80, 'EC packet short enough');
my $ec = substr($pkt, 0, $len, '');
if ($ec_seq == 0 && !exists($udptl_ec_in[$ec_seq])) {
# this happens on T.38=force before the answer
# was seen. seq 0 is generated but not sent as
# we don't have an endpoint yet.
# XXX can this be fixed? queue packet?
;
}
else {
ok ($ec eq $udptl_ec_in[$ec_seq], 'EC packet matches');
}
}
}
else {
ok (substr($pkt, 0, 1, '') eq "\x01", 'FEC span header');
my $nspan = substr($pkt, 0, 1, '');
$nspan = ord($nspan);
ok ($nspan >= 1, 'FEC span min');
my $expspan = $span;
my $expent = $num_ec;
while ($udptl_seq < $expspan * $expent) {
if ($expspan > 1) {
$expspan--;
next;
}
$expent--;
}
ok ($expspan == $nspan, "FEC span $expspan == $nspan");
my $nec = ord(substr($pkt, 0, 1, ''));
ok ($expent == $nec, "FEC num entries $expent == $nec");
# extract all entries and compare with self-generated list
my ($fec_entries, $fec_blob) = fec($udptl_seq, $nec, $nspan, \@udptl_ec_in);
my $recv_blob = '';
for (1 .. $nec) {
my $len = substr($pkt, 0, 1, '');
$len = ord($len);
ok ($len > 0 && $len < 0x80, 'FEC packet short enough');
my $ec = substr($pkt, 0, $len, '');
$recv_blob .= pack('Ca*', $len, $ec);
}
ok ($fec_entries == $nec, "num actual FEC entries $fec_entries == $nec");
ok ($recv_blob eq $fec_blob, 'FEC blob matches');
}
# everything passed, write to T.38 end
ok (syswrite($t38_sink, pack('SSa*', $udptl_seq, length($ifp), $ifp)), 'T.38 writeback');
}
}
# delete to stop PCM player
rtpe_req('delete', "$testname delete", { 'from-tag' => ft() });
undef($t38_src);
undef($t38_sink);
undef($pcm_src);
undef($pcm_sink);
if ($t38_pid) {
ok (waitpid($t38_pid, 0), 'T.38 spandsp finished');
undef($t38_pid);
}
if ($pcm_pid) {
ok (waitpid($pcm_pid, 0), 'PCM spandsp finished');
undef($pcm_pid);
}
ok (-f 'out.tif', 'output file exists');
ok (-s 'out.tif' > 10000, 'output file large enough');
unlink('out.tif');
}
($sock_a, $sock_b) = new_call([qw(198.51.100.1 4020)], [qw(198.51.100.3 4022)]);
($port_a) = offer('T.38 after re-invite', { ICE => 'remove',
}, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.3
s=tester
t=0 0
m=audio 4020 RTP/AVP 8 0
c=IN IP4 198.51.100.3
a=sendrecv
--------------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.3
s=tester
t=0 0
m=audio PORT RTP/AVP 8 0
c=IN IP4 203.0.113.1
a=rtpmap:8 PCMA/8000
a=rtpmap:0 PCMU/8000
a=sendrecv
a=rtcp:PORT
SDP
($port_b) = answer('T.38 after re-invite', { ICE => 'remove' }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.3
s=tester
t=0 0
m=audio 4022 RTP/AVP 8 0
c=IN IP4 198.51.100.3
a=sendrecv
----------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.3
s=tester
t=0 0
m=audio PORT RTP/AVP 8 0
c=IN IP4 203.0.113.1
a=rtpmap:8 PCMA/8000
a=rtpmap:0 PCMU/8000
a=sendrecv
a=rtcp:PORT
SDP
snd($sock_a, $port_b, rtp(8, 1000, 3000, 0x1234, "\x00" x 160));
rcv($sock_b, $port_a, rtpm(8, 1000, 3000, 0x1234, "\x00" x 160));
snd($sock_b, $port_a, rtp(8, 4000, 6000, 0x2bc3, "\x00" x 160));
rcv($sock_a, $port_b, rtpm(8, 4000, 6000, 0x2bc3, "\x00" x 160));
($port_a) = offer('T.38 after re-invite', { 'T.38' => [ 'force' ], ICE => 'remove',
}, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.3
s=tester
t=0 0
m=audio 4020 RTP/AVP 8 0
c=IN IP4 198.51.100.3
a=sendrecv
--------------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.3
s=tester
t=0 0
m=image PORT udptl t38
c=IN IP4 203.0.113.1
a=T38FaxVersion:0
a=T38MaxBitRate:14400
a=T38FaxRateManagement:transferredTCF
a=T38FaxMaxBuffer:1800
a=T38FaxMaxDatagram:512
a=T38FaxUdpEC:t38UDPRedundancy
a=sendrecv
SDP
($port_b) = answer('T.38 after re-invite', { ICE => 'remove' }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=image 4022 udptl t38
c=IN IP4 198.51.100.1
a=sendrecv
a=T38FaxVersion:0
a=T38MaxBitRate:14400
a=T38FaxRateManagement:transferredTCF
a=T38FaxMaxBuffer:262
a=T38FaxMaxDatagram:300
a=T38FaxUdpEC:t38UDPRedundancy
----------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=audio PORT RTP/AVP 8
c=IN IP4 203.0.113.1
a=rtpmap:8 PCMA/8000
a=sendrecv
a=rtcp:PORT
SDP
t38_gw_test('T.38 after re-invite',
'./spandsp_send_fax_pcm test.tif',
'./spandsp_recv_fax_t38 out.tif',
reverse => 1, seq => 4001);
($sock_a, $sock_b) = new_call([qw(198.51.100.1 4016)], [qw(198.51.100.3 4018)]);
($port_a) = offer('plain T.38, reverse invite', { 'T.38' => [ 'force' ], ICE => 'remove',
}, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.3
s=tester
t=0 0
m=audio 4016 RTP/AVP 8 0
c=IN IP4 198.51.100.3
a=sendrecv
--------------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.3
s=tester
t=0 0
m=image PORT udptl t38
c=IN IP4 203.0.113.1
a=T38FaxVersion:0
a=T38MaxBitRate:14400
a=T38FaxRateManagement:transferredTCF
a=T38FaxMaxBuffer:1800
a=T38FaxMaxDatagram:512
a=T38FaxUdpEC:t38UDPRedundancy
a=sendrecv
SDP
($port_b) = answer('plain T.38, reverse invite', { ICE => 'remove' }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=image 4018 udptl t38
c=IN IP4 198.51.100.1
a=sendrecv
a=T38FaxVersion:0
a=T38MaxBitRate:14400
a=T38FaxRateManagement:transferredTCF
a=T38FaxMaxBuffer:262
a=T38FaxMaxDatagram:300
a=T38FaxUdpEC:t38UDPRedundancy
----------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=audio PORT RTP/AVP 8
c=IN IP4 203.0.113.1
a=rtpmap:8 PCMA/8000
a=sendrecv
a=rtcp:PORT
SDP
t38_gw_test('plain T.38, reverse invite',
'./spandsp_send_fax_pcm test.tif',
'./spandsp_recv_fax_t38 out.tif',
reverse => 1);
($sock_a, $sock_b) = new_call([qw(198.51.100.1 4000)], [qw(198.51.100.3 4002)]);
($port_a) = offer('plain T.38, forward invite', { 'T.38' => [ 'decode' ], ICE => 'remove',
'codec' => { 'transcode' => ['PCMA'] } }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=image 4000 udptl t38
c=IN IP4 198.51.100.1
a=sendrecv
a=T38FaxVersion:0
a=T38MaxBitRate:14400
a=T38FaxRateManagement:transferredTCF
a=T38FaxMaxBuffer:262
a=T38FaxMaxDatagram:300
a=T38FaxUdpEC:t38UDPRedundancy
----------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=audio PORT RTP/AVP 8
c=IN IP4 203.0.113.1
a=rtpmap:8 PCMA/8000
a=sendrecv
a=rtcp:PORT
SDP
($port_b) = answer('plain T.38, forward invite', { ICE => 'remove' }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.3
s=tester
t=0 0
m=audio 4002 RTP/AVP 8
c=IN IP4 198.51.100.3
a=sendrecv
--------------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.3
s=tester
t=0 0
m=image PORT udptl t38
c=IN IP4 203.0.113.1
a=T38FaxVersion:0
a=T38MaxBitRate:14400
a=T38FaxRateManagement:transferredTCF
a=T38FaxMaxBuffer:1800
a=T38FaxMaxDatagram:512
a=T38FaxUdpEC:t38UDPRedundancy
a=sendrecv
SDP
t38_gw_test('plain T.38, forward invite',
'./spandsp_send_fax_pcm test.tif',
'./spandsp_recv_fax_t38 out.tif');
($sock_a, $sock_b) = new_call([qw(198.51.100.1 4004)], [qw(198.51.100.3 4006)]);
($port_a) = offer('plain T.38, forward invite, reverse receive', { 'T.38' => [ 'decode' ], ICE => 'remove',
'codec' => { 'transcode' => ['PCMA'] } }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=image 4004 udptl t38
c=IN IP4 198.51.100.1
a=sendrecv
a=T38FaxVersion:0
a=T38MaxBitRate:14400
a=T38FaxRateManagement:transferredTCF
a=T38FaxMaxBuffer:262
a=T38FaxMaxDatagram:300
a=T38FaxUdpEC:t38UDPRedundancy
----------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=audio PORT RTP/AVP 8
c=IN IP4 203.0.113.1
a=rtpmap:8 PCMA/8000
a=sendrecv
a=rtcp:PORT
SDP
($port_b) = answer('plain T.38, forward invite, reverse receive', { ICE => 'remove' }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.3
s=tester
t=0 0
m=audio 4006 RTP/AVP 8
c=IN IP4 198.51.100.3
a=sendrecv
--------------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.3
s=tester
t=0 0
m=image PORT udptl t38
c=IN IP4 203.0.113.1
a=T38FaxVersion:0
a=T38MaxBitRate:14400
a=T38FaxRateManagement:transferredTCF
a=T38FaxMaxBuffer:1800
a=T38FaxMaxDatagram:512
a=T38FaxUdpEC:t38UDPRedundancy
a=sendrecv
SDP
t38_gw_test('plain T.38, forward invite, reverse receive',
'./spandsp_recv_fax_pcm out.tif',
'./spandsp_send_fax_t38 test.tif');
($sock_a, $sock_b) = new_call([qw(198.51.100.1 4008)], [qw(198.51.100.3 4010)]);
($port_a) = offer('FEC', { 'T.38' => [ 'decode' ], ICE => 'remove',
'codec' => { 'transcode' => ['PCMA'] } }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=image 4008 udptl t38
c=IN IP4 198.51.100.1
a=sendrecv
a=T38FaxVersion:0
a=T38MaxBitRate:14400
a=T38FaxRateManagement:transferredTCF
a=T38FaxMaxBuffer:262
a=T38FaxMaxDatagram:300
a=T38FaxUdpEC:t38UDPFEC
----------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=audio PORT RTP/AVP 8
c=IN IP4 203.0.113.1
a=rtpmap:8 PCMA/8000
a=sendrecv
a=rtcp:PORT
SDP
($port_b) = answer('FEC', { ICE => 'remove' }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.3
s=tester
t=0 0
m=audio 4010 RTP/AVP 8
c=IN IP4 198.51.100.3
a=sendrecv
--------------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.3
s=tester
t=0 0
m=image PORT udptl t38
c=IN IP4 203.0.113.1
a=T38FaxVersion:0
a=T38MaxBitRate:14400
a=T38FaxRateManagement:transferredTCF
a=T38FaxMaxBuffer:1800
a=T38FaxMaxDatagram:512
a=T38FaxUdpEC:t38UDPFEC
a=sendrecv
SDP
t38_gw_test('FEC',
'./spandsp_send_fax_pcm test.tif',
'./spandsp_recv_fax_t38 out.tif',
span => 3);
($sock_a, $sock_b) = new_call([qw(198.51.100.1 4012)], [qw(198.51.100.3 4014)]);
($port_a) = offer('FEC span 5', { 'T.38' => [ 'decode' ], ICE => 'remove',
'codec' => { 'transcode' => ['PCMA'] } }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=image 4012 udptl t38
c=IN IP4 198.51.100.1
a=sendrecv
a=T38FaxVersion:0
a=T38MaxBitRate:14400
a=T38FaxRateManagement:transferredTCF
a=T38FaxMaxBuffer:262
a=T38FaxMaxDatagram:300
a=T38FaxUdpEC:t38UDPFEC
a=T38FaxUdpFECMaxSpan:5
----------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=audio PORT RTP/AVP 8
c=IN IP4 203.0.113.1
a=rtpmap:8 PCMA/8000
a=sendrecv
a=rtcp:PORT
SDP
($port_b) = answer('FEC span 5', { ICE => 'remove' }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.3
s=tester
t=0 0
m=audio 4014 RTP/AVP 8
c=IN IP4 198.51.100.3
a=sendrecv
--------------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.3
s=tester
t=0 0
m=image PORT udptl t38
c=IN IP4 203.0.113.1
a=T38FaxVersion:0
a=T38MaxBitRate:14400
a=T38FaxRateManagement:transferredTCF
a=T38FaxMaxBuffer:1800
a=T38FaxMaxDatagram:512
a=T38FaxUdpEC:t38UDPFEC
a=sendrecv
SDP
t38_gw_test('FEC span 5',
'./spandsp_send_fax_pcm test.tif',
'./spandsp_recv_fax_t38 out.tif',
span => 5);
new_call;
offer('override T.38 version control', { 'T.38' => [ 'decode' ] }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=image 4000 udptl t38
c=IN IP4 198.51.100.1
a=sendrecv
a=T38FaxVersion:1
a=T38MaxBitRate:14400
a=T38FaxRateManagement:transferredTCF
a=T38FaxMaxBuffer:262
a=T38FaxMaxDatagram:300
a=T38FaxUdpEC:t38UDPRedundancy
----------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=audio PORT RTP/AVP 0 8
c=IN IP4 203.0.113.1
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=sendrecv
a=rtcp:PORT
SDP
answer('override T.38 version control', { }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.3
s=tester
t=0 0
m=audio 4002 RTP/AVP 8
c=IN IP4 198.51.100.3
a=sendrecv
--------------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.3
s=tester
t=0 0
m=image PORT udptl t38
c=IN IP4 203.0.113.1
a=T38FaxVersion:1
a=T38MaxBitRate:14400
a=T38FaxRateManagement:transferredTCF
a=T38FaxMaxBuffer:1800
a=T38FaxMaxDatagram:512
a=T38FaxUdpEC:t38UDPRedundancy
a=sendrecv
SDP
new_call;
offer('override T.38 version', { 'T.38' => [ 'decode' ], 'T.38 version' => 0 }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=image 4000 udptl t38
c=IN IP4 198.51.100.1
a=sendrecv
a=T38FaxVersion:1
a=T38MaxBitRate:14400
a=T38FaxRateManagement:transferredTCF
a=T38FaxMaxBuffer:262
a=T38FaxMaxDatagram:300
a=T38FaxUdpEC:t38UDPRedundancy
----------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=audio PORT RTP/AVP 0 8
c=IN IP4 203.0.113.1
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=sendrecv
a=rtcp:PORT
SDP
answer('override T.38 version', { }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.3
s=tester
t=0 0
m=audio 4002 RTP/AVP 8
c=IN IP4 198.51.100.3
a=sendrecv
--------------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.3
s=tester
t=0 0
m=image PORT udptl t38
c=IN IP4 203.0.113.1
a=T38FaxVersion:0
a=T38MaxBitRate:14400
a=T38FaxRateManagement:transferredTCF
a=T38FaxMaxBuffer:1800
a=T38FaxMaxDatagram:512
a=T38FaxUdpEC:t38UDPRedundancy
a=sendrecv
SDP
# XXX packet loss tests
# XXX tests of different SDP options
#done_testing;NGCP::Rtpengine::AutoTest::terminate('f00');exit;
done_testing();