diff --git a/perl/ICE.pm b/perl/ICE.pm index be3825499..8b04d8303 100644 --- a/perl/ICE.pm +++ b/perl/ICE.pm @@ -554,6 +554,7 @@ sub check_nominations { @nominated = sort_pairs(\@nominated); my $pair = $nominated[0]; $self->debug("highest priority nominated pair is $pair->{foundation}\n"); + $self->{nominated_pair} = $pair; } sub stun_handler_binding_success { @@ -595,6 +596,7 @@ sub check_to_nominate { $self->{controlling} or return; $self->{start_nominating} && time() < $self->{start_nominating} and return; $self->{nominate} and return; + @{$self->{triggered_checks}} and return; my @succeeded; @@ -625,6 +627,7 @@ sub check_to_nominate { $self->{nominate} = 1; $pair->{nominate} = 1; $self->{start_nominating} = 0; + $self->{nominated_pair} = $pair; $pair->debug("nominating\n"); for my $comp (@{$pair->{components}}) { @@ -779,6 +782,21 @@ sub sort_pairs { return sort {$a->priority() <=> $b->priority()} @$pair_list; } +sub get_send_component { + my ($self, $component) = @_; + + my $pair = $self->{nominated_pair}; + + if (!$pair) { + my @pairs = values(%{$self->{candidate_pairs}}); + @pairs = sort_pairs(\@pairs); + $pair = $pairs[0]; + } + + return ($pair->{components}->[$component]->{local}->{socket}, + $pair->{components}->[$component]->{remote}->{packed_peer}); +} + package ICE::Candidate; sub debug { diff --git a/perl/RTP.pm b/perl/RTP.pm index 4c4ab7cb2..762bcaccd 100644 --- a/perl/RTP.pm +++ b/perl/RTP.pm @@ -6,13 +6,12 @@ use Time::HiRes qw(time); use Math::BigInt; sub new { - my ($class, $local_socket, $dest) = @_; + my ($class, $cb_obj) = @_; my $self = {}; bless $self, $class; - $self->{local_socket} = $local_socket; - $self->{destination} = $dest; + $self->{cb_obj} = $cb_obj; $self->{ssrc} = int(rand(2**32)); $self->{next_send} = time(); @@ -33,7 +32,7 @@ sub timer { my $hdr = pack("CCnNN", 0x80, 0x00, $self->{seq}, $self->{timestamp}->bstr(), $self->{ssrc}); my $payload = chr(rand(256)) x $self->{payload}; # XXX adapt to codec - $self->{local_socket}->send($hdr . $payload, 0, $self->{destination}); + $self->{cb_obj}->rtp_send($hdr . $payload); $self->{seq}++; $self->{seq} > 0xffff and $self->{seq} -= 0x10000; diff --git a/perl/Rtpengine/Test.pm b/perl/Rtpengine/Test.pm index 4d06c384b..0988c00eb 100644 --- a/perl/Rtpengine/Test.pm +++ b/perl/Rtpengine/Test.pm @@ -28,15 +28,17 @@ sub new { my @intfs = Net::Interface->interfaces(); - my @v4 = map {$_->address(&IO::Socket::AF_INET)} @intfs; - @v4 = map {Socket6::inet_ntop(&IO::Socket::AF_INET, $_)} @v4; + my @v4 = map {$_->address(&AF_INET)} @intfs; + @v4 = map {Socket6::inet_ntop(&AF_INET, $_)} @v4; @v4 = grep {$_ !~ /^127\./} @v4; + @v4 = map { { address => $_, domain => &AF_INET } } @v4; @v4 or die("no IPv4 addresses found"); - my @v6 = map {$_->address(&IO::Socket::AF_INET6)} @intfs; - @v6 = map {Socket6::inet_ntop(&IO::Socket::AF_INET6, $_)} @v6; + my @v6 = map {$_->address(&AF_INET6)} @intfs; + @v6 = map {Socket6::inet_ntop(&AF_INET6, $_)} @v6; @v6 = grep {$_ !~ /^::|^fe80:/} @v6; - @v4 or die("no IPv6 addresses found"); + @v6 = map { { address => $_, domain => &AF_INET6 } } @v6; + @v6 or die("no IPv6 addresses found"); $self->{v4_addresses} = \@v4; $self->{v6_addresses} = \@v6; @@ -110,6 +112,8 @@ sub mux_timeout { package Rtpengine::Test::Client; +use Socket; + sub _new { my ($class, $parent, %args) = @_; @@ -126,10 +130,15 @@ sub _new { # XXX support rtcp-mux and rtcp-less media for my $address (@addresses) { - my $rtp = IO::Socket::IP->new(Type => &Socket::SOCK_DGRAM, Proto => 'udp', - LocalHost => $address, LocalPort => $parent->{media_port}++) or die($address); - my $rtcp = IO::Socket::IP->new(Type => &Socket::SOCK_DGRAM, Proto => 'udp', - LocalHost => $address, LocalPort => $parent->{media_port}++) or die($address); + $args{domain} && $args{domain} != $address->{domain} and next; + + my $rtp = IO::Socket::IP->new(Type => &SOCK_DGRAM, Proto => 'udp', + LocalHost => $address->{address}, LocalPort => $parent->{media_port}++) + or die($address->{address}); + my $rtcp = IO::Socket::IP->new(Type => &SOCK_DGRAM, Proto => 'udp', + LocalHost => $address->{address}, LocalPort => $parent->{media_port}++) + or die($address->{address}); + push(@sockets, [$rtp, $rtcp]); push(@rtp, $rtp); push(@rtcp, $rtcp); @@ -138,6 +147,8 @@ sub _new { $parent->{mux}->set_timeout($rtp, 0.01); # XXX overkill, only need this on one } + @sockets or die; + $self->{sockets} = \@sockets; $self->{rtp_sockets} = \@rtp; $self->{rtcp_sockets} = \@rtcp; @@ -172,9 +183,40 @@ sub _new { return $self; } +sub _packet_send { + my ($self, $component, $s) = @_; + + my $local_socket = $self->{main_sockets}->[$component]; + + my $dest; + + if (!$self->{ice}) { + if ($self->{remote_media}) { + $dest = $component == 0 ? $self->{remote_media}->endpoint() + : $self->{remote_media}->rtcp_endpoint(); + } + else { + $dest = $self->{component_peers}->[$component] + } + } + else { + ($local_socket, $dest) = $self->{ice}->get_send_component($component); + } + + $local_socket->send($s, 0, $dest); +} + sub dtls_send { my ($self, $component, $s) = @_; - $self->{main_sockets}->[$component]->send($s, 0, $self->{component_peers}->[$component]); + $self->_packet_send($component, $s); +} +sub rtp_send { + my ($self, $s) = @_; + $self->_packet_send(0, $s); +} +sub rtcp_send { + my ($self, $s) = @_; + $self->_packet_send(1, $s); } sub _default_req_args { @@ -182,7 +224,7 @@ sub _default_req_args { my $req = { command => $cmd, 'call-id' => $self->{parent}->{callid} }; - for my $cp (qw(sdp from-tag to-tag ICE transport-protocol)) { + for my $cp (qw(sdp from-tag to-tag ICE transport-protocol address-family)) { $args{$cp} and $req->{$cp} = $args{$cp}; } @@ -278,7 +320,7 @@ sub start_rtp { my ($self) = @_; $self->{rtp} and die; my $dest = $self->{remote_media}->endpoint(); - $self->{rtp} = RTP->new($self->{rtp_sockets}->[0], $dest) or die; + $self->{rtp} = RTP->new($self) or die; } 1; diff --git a/utils/test-basic.pl b/utils/test-basic.pl index 43da53bb2..6d579145c 100644 --- a/utils/test-basic.pl +++ b/utils/test-basic.pl @@ -3,10 +3,11 @@ use strict; use warnings; use Rtpengine::Test; +use IO::Socket; my $r = Rtpengine::Test->new(); -my $a = $r->client(); -my $b = $r->client(); +my $a = $r->client(domain => &Socket::AF_INET); +my $b = $r->client(domain => &Socket::AF_INET); $r->timer_once(3, sub { $b->answer($a, ICE => 'remove'); $a->start_rtp(); }); $r->timer_once(10, sub { $r->stop(); }); diff --git a/utils/test-ice.pl b/utils/test-ice.pl index 31dbc2f8e..f495bb92a 100644 --- a/utils/test-ice.pl +++ b/utils/test-ice.pl @@ -6,10 +6,11 @@ use Rtpengine::Test; my $r = Rtpengine::Test->new(); my $a = $r->client(ice => 1); -my $b = $r->client(); +my $b = $r->client(domain => &Socket::AF_INET); $r->timer_once(3, sub { $b->answer($a) }); +$r->timer_once(5, sub { $a->start_rtp(); $b->start_rtp(); }); -$a->offer($b, ICE => 'remove'); +$a->offer($b, ICE => 'remove', 'address-family' => 'IP4'); $r->run();