Bug 1189041 - Add option to only gather addresses for default route. r=bwc

This commit is contained in:
EKR 2015-08-12 10:53:15 -04:00
parent a1a81c8e89
commit 08b6404747
15 changed files with 310 additions and 36 deletions

View File

@ -738,7 +738,7 @@ int NrSocket::connect(nr_transport_addr *addr) {
ASSERT_ON_THREAD(ststhread_);
int r,_status;
PRNetAddr naddr;
int32_t status;
int32_t connect_status, getsockname_status;
if ((r=nr_transport_addr_to_praddr(addr, &naddr)))
ABORT(r);
@ -749,13 +749,28 @@ int NrSocket::connect(nr_transport_addr *addr) {
// Note: this just means we tried to connect, not that we
// are actually live.
connect_invoked_ = true;
status = PR_Connect(fd_, &naddr, PR_INTERVAL_NO_WAIT);
connect_status = PR_Connect(fd_, &naddr, PR_INTERVAL_NO_WAIT);
if (connect_status != PR_SUCCESS) {
if (PR_GetError() != PR_IN_PROGRESS_ERROR)
ABORT(R_IO_ERROR);
}
if (status != PR_SUCCESS) {
if (PR_GetError() == PR_IN_PROGRESS_ERROR)
ABORT(R_WOULDBLOCK);
// If our local address is wildcard, then fill in the
// address now.
if(nr_transport_addr_is_wildcard(&my_addr_)){
getsockname_status = PR_GetSockName(fd_, &naddr);
if (getsockname_status != PR_SUCCESS){
r_log(LOG_GENERIC, LOG_CRIT, "Couldn't get sock name for socket");
ABORT(R_INTERNAL);
}
ABORT(R_IO_ERROR);
if((r=nr_praddr_to_transport_addr(&naddr,&my_addr_,addr->protocol,1)))
ABORT(r);
}
// Now return the WOULDBLOCK if needed.
if (connect_status != PR_SUCCESS) {
ABORT(R_WOULDBLOCK);
}
_status=0;

View File

@ -382,9 +382,9 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
bool allow_loopback,
bool tcp_enabled,
bool allow_link_local,
bool hide_non_default,
Policy policy) {
RefPtr<NrIceCtx> ctx = new NrIceCtx(name, offerer, policy);
RefPtr<NrIceCtx> ctx = new NrIceCtx(name, offerer, policy);
// Initialize the crypto callbacks and logging stuff
if (!initialized) {
@ -490,6 +490,9 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
flags |= NR_ICE_CTX_FLAGS_RELAY_ONLY;
}
if (hide_non_default)
flags |= NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS;
r = nr_ice_ctx_create(const_cast<char *>(name.c_str()), flags,
&ctx->ctx_);
if (r) {

View File

@ -213,12 +213,14 @@ class NrIceCtx {
ICE_POLICY_ALL
};
// TODO(ekr@rtfm.com): Too many bools here. Bug 1193437.
static RefPtr<NrIceCtx> Create(const std::string& name,
bool offerer,
bool set_interface_priorities = true,
bool allow_loopback = false,
bool tcp_enabled = true,
bool allow_link_local = false,
bool hide_non_default = false,
Policy policy = ICE_POLICY_ALL);
// Deinitialize all ICE global state. Used only for testing.

View File

@ -250,12 +250,14 @@ class SchedulableTrickleCandidate {
class IceTestPeer : public sigslot::has_slots<> {
public:
// TODO(ekr@rtfm.com): Convert to flags when NrIceCtx::Create() does.
// Bug 1193437.
IceTestPeer(const std::string& name, bool offerer, bool set_priorities,
bool allow_loopback = false, bool enable_tcp = true) :
bool allow_loopback = false, bool enable_tcp = true,
bool allow_link_local = false, bool hide_non_default = false) :
name_(name),
ice_ctx_(NrIceCtx::Create(name, offerer, set_priorities, allow_loopback,
enable_tcp)),
enable_tcp, allow_link_local, hide_non_default)),
streams_(),
candidates_(),
gathering_complete_(false),
@ -1061,6 +1063,22 @@ class IceTestPeer : public sigslot::has_slots<> {
SetControlling(NrIceCtx::ICE_CONTROLLED);
}
nsresult GetDefaultCandidate(unsigned int stream, NrIceCandidate* cand) {
nsresult rv;
test_utils->sts_target()->Dispatch(
WrapRunnableRet(&rv, this,
&IceTestPeer::GetDefaultCandidate_s,
stream, cand),
NS_DISPATCH_SYNC);
return rv;
}
nsresult GetDefaultCandidate_s(unsigned int stream, NrIceCandidate* cand) {
return streams_[stream]->GetDefaultCandidate(1, cand);
}
private:
std::string name_;
nsRefPtr<NrIceCtx> ice_ctx_;
@ -1245,6 +1263,17 @@ class IceGatherTest : public ::testing::Test {
return false;
}
void DumpCandidates(unsigned int stream) {
std::vector<std::string> candidates = peer_->GetCandidates(stream);
std::cerr << "Candidates for stream " << stream << "->"
<< candidates.size() << std::endl;
for (auto c : candidates) {
std::cerr << "Candidate: " << c << std::endl;
}
}
protected:
mozilla::ScopedDeletePtr<IceTestPeer> peer_;
};
@ -1288,24 +1317,28 @@ class IceConnectTest : public ::testing::Test {
p2_->RemoveStream(index);
}
void Init(bool set_priorities, bool allow_loopback, bool enable_tcp) {
void Init(bool set_priorities, bool allow_loopback, bool enable_tcp,
bool default_only = false) {
if (!initted_) {
p1_ = new IceTestPeer("P1", true, set_priorities, allow_loopback,
enable_tcp);
enable_tcp, false, default_only);
p2_ = new IceTestPeer("P2", false, set_priorities, allow_loopback,
enable_tcp);
enable_tcp, false, default_only);
}
initted_ = true;
}
bool Gather(unsigned int waitTime = kDefaultTimeout) {
bool Gather(unsigned int waitTime = kDefaultTimeout,
bool setupStunServers = true) {
Init(false, false, false);
if (use_nat_) {
// If we enable nat simulation, but still use a real STUN server somewhere
// on the internet, we will see failures if there is a real NAT in
// addition to our simulated one, particularly if it disallows
// hairpinning.
UseTestStunServer();
if (setupStunServers) {
UseTestStunServer();
}
p1_->UseNat();
p2_->UseNat();
p1_->SetFilteringType(filtering_type_);
@ -1314,13 +1347,13 @@ class IceConnectTest : public ::testing::Test {
p2_->SetMappingType(mapping_type_);
p1_->SetBlockUdp(block_udp_);
p2_->SetBlockUdp(block_udp_);
} else {
} else if (setupStunServers) {
std::vector<NrIceStunServer> stun_servers;
stun_servers.push_back(*NrIceStunServer::Create(g_stun_server_address,
kDefaultStunServerPort, kNrIceTransportUdp));
kDefaultStunServerPort, kNrIceTransportUdp));
stun_servers.push_back(*NrIceStunServer::Create(g_stun_server_address,
kDefaultStunServerPort, kNrIceTransportTcp));
kDefaultStunServerPort, kNrIceTransportTcp));
p1_->SetStunServers(stun_servers);
p2_->SetStunServers(stun_servers);
@ -1645,6 +1678,19 @@ TEST_F(IceGatherTest, TestGatherFakeStunServerIpAddress) {
Gather();
}
TEST_F(IceGatherTest, TestGatherStunServerIpAddressDefaultRouteOnly) {
if (g_stun_server_address.empty()) {
return;
}
peer_ = new IceTestPeer("P1", true, false, false, false, false, true);
peer_->AddStream(1);
peer_->SetStunServer(g_stun_server_address, kDefaultStunServerPort);
peer_->SetFakeResolver();
Gather();
ASSERT_FALSE(StreamHasMatchingCandidate(0, " host "));
}
TEST_F(IceGatherTest, TestGatherFakeStunServerHostname) {
if (g_stun_server_hostname.empty()) {
return;
@ -1768,6 +1814,14 @@ TEST_F(IceGatherTest, TestGatherDNSStunBogusHostnameTcp) {
Gather();
}
TEST_F(IceGatherTest, TestDefaultCandidate) {
EnsurePeer();
peer_->SetStunServer(g_stun_server_hostname, kDefaultStunServerPort);
Gather();
NrIceCandidate default_candidate;
ASSERT_TRUE(NS_SUCCEEDED(peer_->GetDefaultCandidate(0, &default_candidate)));
}
TEST_F(IceGatherTest, TestGatherTurn) {
EnsurePeer();
if (g_turn_server.empty())
@ -1921,6 +1975,37 @@ TEST_F(IceGatherTest, TestStunServerTrickle) {
ASSERT_TRUE(StreamHasMatchingCandidate(0, "192.0.2.1"));
}
// Test default route only with our fake STUN server and
// apparently NATted.
TEST_F(IceGatherTest, TestFakeStunServerNatedDefaultRouteOnly) {
peer_ = new IceTestPeer("P1", true, false, false, false, false, true);
peer_->AddStream(1);
UseFakeStunUdpServerWithResponse("192.0.2.1", 3333);
Gather(0);
WaitForGather();
DumpCandidates(0);
ASSERT_FALSE(StreamHasMatchingCandidate(0, "host"));
ASSERT_TRUE(StreamHasMatchingCandidate(0, "srflx"));
NrIceCandidate default_candidate;
nsresult rv = peer_->GetDefaultCandidate(0, &default_candidate);
if (NS_SUCCEEDED(rv)) {
ASSERT_NE(NrIceCandidate::ICE_HOST, default_candidate.type);
}
}
// Test default route only with our fake STUN server and
// apparently non-NATted.
TEST_F(IceGatherTest, TestFakeStunServerNoNatDefaultRouteOnly) {
peer_ = new IceTestPeer("P1", true, false, false, false, false, true);
peer_->AddStream(1);
UseTestStunServer();
Gather(0);
WaitForGather();
DumpCandidates(0);
ASSERT_FALSE(StreamHasMatchingCandidate(0, "host"));
ASSERT_TRUE(StreamHasMatchingCandidate(0, "srflx"));
}
TEST_F(IceGatherTest, TestStunTcpServerTrickle) {
UseFakeStunTcpServerWithResponse("192.0.3.1", 3333);
TestStunTcpServer::GetInstance(AF_INET)->SetActive(false);
@ -1991,6 +2076,16 @@ TEST_F(IceConnectTest, DISABLED_TestConnectTcpSo) {
Connect();
}
// Disabled because this breaks with hairpinning.
TEST_F(IceConnectTest, DISABLED_TestConnectDefaultRouteOnly) {
Init(false, false, false, true);
AddStream("first", 1);
ASSERT_TRUE(Gather());
SetExpectedTypes(NrIceCandidate::Type::ICE_SERVER_REFLEXIVE,
NrIceCandidate::Type::ICE_SERVER_REFLEXIVE, kNrIceTransportTcp);
Connect();
}
TEST_F(IceConnectTest, TestLoopbackOnlySortOf) {
Init(false, true, false);
AddStream("first", 1);
@ -2000,7 +2095,6 @@ TEST_F(IceConnectTest, TestLoopbackOnlySortOf) {
Connect();
}
TEST_F(IceConnectTest, TestConnectBothControllingP1Wins) {
AddStream("first", 1);
p1_->SetTiebreaker(1);
@ -2096,6 +2190,31 @@ TEST_F(IceConnectTest, TestConnectFullCone) {
Connect();
}
TEST_F(IceConnectTest, TestConnectNoNatRouteOnly) {
Init(false, false, false, true);
AddStream("first", 1);
UseTestStunServer();
// Because we are connecting from our host candidate to the
// other side's apparent srflx (which is also their host)
// we see a host/srflx pair.
SetExpectedTypes(NrIceCandidate::Type::ICE_HOST,
NrIceCandidate::Type::ICE_SERVER_REFLEXIVE);
ASSERT_TRUE(Gather(kDefaultTimeout, false));
Connect();
}
TEST_F(IceConnectTest, TestConnectFullConeDefaultRouteOnly) {
Init(false, false, false, true);
AddStream("first", 1);
UseNat();
SetFilteringType(TestNat::ENDPOINT_INDEPENDENT);
SetMappingType(TestNat::ENDPOINT_INDEPENDENT);
SetExpectedTypes(NrIceCandidate::Type::ICE_SERVER_REFLEXIVE,
NrIceCandidate::Type::ICE_SERVER_REFLEXIVE);
ASSERT_TRUE(Gather());
Connect();
}
TEST_F(IceConnectTest, TestGatherAddressRestrictedCone) {
AddStream("first", 1);
UseNat();

View File

@ -539,7 +539,7 @@ int TestStunTcpServer::TryOpenListenSocket(nr_local_addr* addr, uint16_t port) {
return r;
if (ice_ctx_ == NULL)
ice_ctx_ = NrIceCtx::Create("stun", true);
ice_ctx_ = NrIceCtx::Create("stun", false, false, false, false, false, false);
//TODO (nils@mozilla.com) can we replace this with a more basic TCP socket
// alternative which would allow us to remove the framing argument from the

View File

@ -504,7 +504,7 @@ int main(int argc, char **argv)
std::string dummy("dummy");
RUN_ON_THREAD(test_utils->sts_target(),
WrapRunnableNM(&NrIceCtx::Create,
dummy, false, false, false, false, false,
dummy, false, false, false, false, false, false,
NrIceCtx::ICE_POLICY_ALL),
NS_DISPATCH_SYNC);

View File

@ -380,7 +380,11 @@ int TestNrSocket::connect(nr_transport_addr *addr) {
return R_INTERNAL;
}
if (!nat_->enabled_ || nat_->is_an_internal_tuple(*addr)) {
if (!nat_->enabled_
|| addr->protocol==IPPROTO_UDP // Horrible hack to allow default address
// discovery to work. Only works because
// we don't normally connect on UDP.
|| nat_->is_an_internal_tuple(*addr)) {
// This will set connect_invoked_
return NrSocket::connect(addr);
}

View File

@ -941,7 +941,8 @@ int nr_ice_format_candidate_attribute(nr_ice_candidate *cand, char *attr, int ma
len=strlen(attr); attr+=len; maxlen-=len;
/* raddr, rport */
raddr = (cand->stream->ctx->flags & NR_ICE_CTX_FLAGS_RELAY_ONLY) ?
raddr = (cand->stream->ctx->flags & NR_ICE_CTX_FLAGS_RELAY_ONLY |
NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS) ?
&cand->addr : &cand->base;
switch(cand->type){
@ -953,7 +954,6 @@ int nr_ice_format_candidate_attribute(nr_ice_candidate *cand, char *attr, int ma
ABORT(r);
if(r=nr_transport_addr_get_port(raddr,&port))
ABORT(r);
snprintf(attr,maxlen," raddr %s rport %d",addr,port);
break;
case RELAYED:

View File

@ -667,8 +667,9 @@ int nr_ice_component_maybe_prune_candidate(nr_ice_ctx *ctx, nr_ice_component *co
!nr_transport_addr_cmp(&c1->addr,&c2->addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL)){
if((c1->type == c2->type) ||
(c1->type==HOST && c2->type == SERVER_REFLEXIVE) ||
(c2->type==HOST && c1->type == SERVER_REFLEXIVE)){
(!(ctx->flags & NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS) &&
((c1->type==HOST && c2->type == SERVER_REFLEXIVE) ||
(c2->type==HOST && c1->type == SERVER_REFLEXIVE)))){
/*
These are redundant. Remove the lower pri one, or if pairing has
@ -1363,7 +1364,7 @@ int nr_ice_component_get_default_candidate(nr_ice_component *comp, nr_ice_candid
*/
cand=TAILQ_FIRST(&comp->candidates);
while(cand){
if (cand->state == NR_ICE_CAND_STATE_INITIALIZED &&
if (!nr_ice_ctx_hide_candidate(comp->ctx, cand) &&
cand->addr.ip_version == ip_version) {
if (!best_cand) {
best_cand = cand;

View File

@ -1,3 +1,4 @@
/*
Copyright (c) 2007, Adobe Systems, Incorporated
All rights reserved.
@ -505,7 +506,8 @@ void nr_ice_gather_finished_cb(NR_SOCKET s, int h, void *cb_arg)
/* If we are initialized, the candidate wasn't pruned,
and we have a trickle ICE callback fire the callback */
if (ctx->trickle_cb && !was_pruned) {
if (ctx->trickle_cb && !was_pruned &&
!nr_ice_ctx_hide_candidate(ctx, cand)) {
ctx->trickle_cb(ctx->trickle_cb_arg, ctx, cand->stream, cand->component_id, cand);
if (nr_ice_ctx_pair_new_trickle_candidates(ctx, cand)) {
@ -550,21 +552,111 @@ static int nr_ice_ctx_pair_new_trickle_candidates(nr_ice_ctx *ctx, nr_ice_candid
return(_status);
}
/* Get the default address by doing a connect to a known public IP address,
in this case Google public DNS:
int nr_ice_gather(nr_ice_ctx *ctx, NR_async_cb done_cb, void *cb_arg)
IPv4: 8.8.8.8
IPv6: 2001:4860:4860::8888
Then we can do getsockname to get the address. No packets get sent
since this is UDP. It's just a way to get the address.
*/
static int nr_ice_get_default_address(nr_ice_ctx *ctx, int ip_version, nr_transport_addr* addrp)
{
int r,_status;
nr_ice_media_stream *stream;
nr_local_addr addrs[MAXADDRS];
nr_transport_addr addr;
nr_transport_addr remote_addr;
nr_socket *sock=0;
switch(ip_version) {
case NR_IPV4:
if ((r=nr_str_port_to_transport_addr("0.0.0.0", 0, IPPROTO_UDP, &addr)))
ABORT(r);
if ((r=nr_str_port_to_transport_addr("8.8.8.8", 53, IPPROTO_UDP, &remote_addr)))
ABORT(r);
break;
case NR_IPV6:
if ((r=nr_str_port_to_transport_addr("::0", 0, IPPROTO_UDP, &addr)))
ABORT(r);
if ((r=nr_str_port_to_transport_addr("2001:4860:4860::8888", 53, IPPROTO_UDP, &remote_addr)))
ABORT(r);
break;
default:
assert(0);
ABORT(R_INTERNAL);
}
if ((r=nr_socket_factory_create_socket(ctx->socket_factory, &addr, &sock)))
ABORT(r);
if ((r=nr_socket_connect(sock, &remote_addr)))
ABORT(r);
if ((r=nr_socket_getaddr(sock, addrp)))
ABORT(r);
_status=0;
abort:
nr_socket_destroy(&sock);
return(_status);
}
static int nr_ice_get_default_local_address(nr_ice_ctx *ctx, int ip_version, nr_local_addr* addrs, int addr_ct, nr_local_addr *addrp)
{
int r,_status;
nr_transport_addr default_addr;
int i;
if ((r=nr_ice_get_default_address(ctx, ip_version, &default_addr)))
ABORT(r);
for(i=0; i<addr_ct; ++i) {
if (!nr_transport_addr_cmp(&default_addr, &addrs[i].addr,
NR_TRANSPORT_ADDR_CMP_MODE_ADDR)) {
if ((r=nr_local_addr_copy(addrp, &addrs[i])))
ABORT(r);
break;
}
}
if (i==addr_ct)
ABORT(R_NOT_FOUND);
_status=0;
abort:
return(_status);
}
static int nr_ice_get_local_addresses(nr_ice_ctx *ctx)
{
int r,_status;
nr_local_addr local_addrs[MAXADDRS];
nr_local_addr *addrs = 0;
int i,addr_ct;
nr_local_addr default_addrs[2];
int default_addr_ct = 0;
if (!ctx->local_addrs) {
/* First, gather all the local addresses we have */
if(r=nr_stun_find_local_addresses(addrs,MAXADDRS,&addr_ct)) {
if((r=nr_stun_find_local_addresses(local_addrs,MAXADDRS,&addr_ct))) {
r_log(LOG_ICE,LOG_ERR,"ICE(%s): unable to find local addresses",ctx->label);
ABORT(r);
}
if (ctx->flags & NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS) {
/* Get just the default IPv4 and IPv6 addrs */
if(!nr_ice_get_default_local_address(ctx, NR_IPV4, local_addrs, addr_ct,
&default_addrs[default_addr_ct])) {
++default_addr_ct;
}
if(!nr_ice_get_default_local_address(ctx, NR_IPV6, local_addrs, addr_ct,
&default_addrs[default_addr_ct])) {
++default_addr_ct;
}
addrs = default_addrs;
addr_ct = default_addr_ct;
}
else {
addrs = local_addrs;
}
/* Sort interfaces by preference */
if(ctx->interface_prioritizer) {
for(i=0;i<addr_ct;i++){
@ -584,6 +676,19 @@ int nr_ice_gather(nr_ice_ctx *ctx, NR_async_cb done_cb, void *cb_arg)
}
}
_status=0;
abort:
return(_status);
}
int nr_ice_gather(nr_ice_ctx *ctx, NR_async_cb done_cb, void *cb_arg)
{
int r,_status;
nr_ice_media_stream *stream;
if ((r=nr_ice_get_local_addresses(ctx)))
ABORT(r);
if(STAILQ_EMPTY(&ctx->streams)) {
r_log(LOG_ICE,LOG_ERR,"ICE(%s): Missing streams to initialize",ctx->label);
ABORT(R_BAD_ARGS);
@ -811,3 +916,18 @@ int nr_ice_ctx_set_trickle_cb(nr_ice_ctx *ctx, nr_ice_trickle_candidate_cb cb, v
return 0;
}
int nr_ice_ctx_hide_candidate(nr_ice_ctx *ctx, nr_ice_candidate *cand)
{
if (cand->state != NR_ICE_CAND_STATE_INITIALIZED) {
return 1;
}
if (ctx->flags & NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS) {
if (cand->type == HOST)
return 1;
}
return 0;
}

View File

@ -158,6 +158,7 @@ int nr_ice_ctx_create(char *label, UINT4 flags, nr_ice_ctx **ctxp);
#define NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION (1<<2)
#define NR_ICE_CTX_FLAGS_LITE (1<<3)
#define NR_ICE_CTX_FLAGS_RELAY_ONLY (1<<4)
#define NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS (1<<5)
int nr_ice_ctx_destroy(nr_ice_ctx **ctxp);
int nr_ice_gather(nr_ice_ctx *ctx, NR_async_cb done_cb, void *cb_arg);
@ -177,6 +178,7 @@ int nr_ice_ctx_set_interface_prioritizer(nr_ice_ctx *ctx, nr_interface_prioritiz
int nr_ice_ctx_set_turn_tcp_socket_wrapper(nr_ice_ctx *ctx, nr_socket_wrapper_factory *wrapper);
void nr_ice_ctx_set_socket_factory(nr_ice_ctx *ctx, nr_socket_factory *factory);
int nr_ice_ctx_set_trickle_cb(nr_ice_ctx *ctx, nr_ice_trickle_candidate_cb cb, void *cb_arg);
int nr_ice_ctx_hide_candidate(nr_ice_ctx *ctx, nr_ice_candidate *cand);
#define NR_ICE_MAX_ATTRIBUTE_SIZE 256

View File

@ -140,6 +140,7 @@ int nr_ice_media_stream_initialize(nr_ice_ctx *ctx, nr_ice_media_stream *stream)
return(_status);
}
int nr_ice_media_stream_get_attributes(nr_ice_media_stream *stream, char ***attrsp, int *attrctp)
{
int attrct=0;
@ -157,7 +158,7 @@ int nr_ice_media_stream_get_attributes(nr_ice_media_stream *stream, char ***attr
if (comp->state != NR_ICE_COMPONENT_DISABLED) {
cand = TAILQ_FIRST(&comp->candidates);
while(cand){
if (cand->state == NR_ICE_CAND_STATE_INITIALIZED) {
if (!nr_ice_ctx_hide_candidate(stream->ctx, cand)) {
++attrct;
}
@ -189,7 +190,7 @@ int nr_ice_media_stream_get_attributes(nr_ice_media_stream *stream, char ***attr
cand=TAILQ_FIRST(&comp->candidates);
while(cand){
if (cand->state == NR_ICE_CAND_STATE_INITIALIZED) {
if (!nr_ice_ctx_hide_candidate(stream->ctx, cand)) {
assert(index < attrct);
if (index >= attrct)

View File

@ -75,7 +75,7 @@ int nr_sockaddr_to_transport_addr(struct sockaddr *saddr, int protocol, int keep
// addresses, ports in local byte order
int nr_ip4_port_to_transport_addr(UINT4 ip4, UINT2 port, int protocol, nr_transport_addr *addr);
int nr_str_port_to_transport_addr(const char *ip4, UINT2 port, int protocol, nr_transport_addr *addr);
int nr_str_port_to_transport_addr(const char *str, UINT2 port, int protocol, nr_transport_addr *addr);
int nr_ip6_port_to_transport_addr(struct in6_addr* addr6, UINT2 port, int protocol, nr_transport_addr *addr);
int nr_transport_addr_get_addrstring(nr_transport_addr *addr, char *str, int maxlen);

View File

@ -304,10 +304,14 @@ nsresult PeerConnectionMedia::Init(const std::vector<NrIceStunServer>& stun_serv
#if !defined(MOZILLA_EXTERNAL_LINKAGE)
bool ice_tcp = Preferences::GetBool("media.peerconnection.ice.tcp", false);
bool default_address_only = Preferences::GetBool(
"media.peerconnection.ice.default_address_only", false);
#else
bool ice_tcp = false;
bool default_address_only = false;
#endif
// TODO(ekr@rtfm.com): need some way to set not offerer later
// Looks like a bug in the NrIceCtx API.
mIceCtx = NrIceCtx::Create("PC:" + mParentName,
@ -316,6 +320,7 @@ nsresult PeerConnectionMedia::Init(const std::vector<NrIceStunServer>& stun_serv
mParent->GetAllowIceLoopback(),
ice_tcp,
mParent->GetAllowIceLinkLocal(),
default_address_only,
policy);
if(!mIceCtx) {
CSFLogError(logTag, "%s: Failed to create Ice Context", __FUNCTION__);

View File

@ -404,6 +404,8 @@ pref("media.peerconnection.identity.enabled", true);
pref("media.peerconnection.identity.timeout", 10000);
pref("media.peerconnection.ice.stun_client_maximum_transmits", 7);
pref("media.peerconnection.ice.trickle_grace_period", 5000);
pref("media.peerconnection.ice.default_address_only", false);
// These values (aec, agc, and noice) are from media/webrtc/trunk/webrtc/common_types.h
// kXxxUnchanged = 0, kXxxDefault = 1, and higher values are specific to each
// setting (for Xxx = Ec, Agc, or Ns). Defaults are all set to kXxxDefault here.