From 4965ecc09e35935bfdf9a9541b05c28e46faa85b Mon Sep 17 00:00:00 2001 From: "Byron Campen [:bwc]" Date: Wed, 22 Apr 2015 15:02:50 -0500 Subject: [PATCH] Bug 797262 - IPV6 support for webrtc. r=drno --- media/mtransport/gonk_addrs.cpp | 5 +- media/mtransport/nr_socket_prsock.cpp | 42 +- media/mtransport/nricectx.cpp | 7 +- media/mtransport/nricectx.h | 3 +- media/mtransport/nriceresolver.cpp | 15 +- media/mtransport/nriceresolverfake.cpp | 4 +- media/mtransport/nriceresolverfake.h | 33 +- media/mtransport/nrinterfaceprioritizer.cpp | 10 +- media/mtransport/stun_udp_socket_filter.cpp | 61 +- .../test/buffered_stun_socket_unittest.cpp | 4 +- media/mtransport/test/ice_unittest.cpp | 219 +++++-- .../test/multi_tcp_socket_unittest.cpp | 2 +- .../test/proxy_tunnel_socket_unittest.cpp | 6 +- media/mtransport/test/stunserver.cpp | 86 ++- media/mtransport/test/stunserver.h | 13 +- .../test/test_nr_socket_unittest.cpp | 2 +- media/mtransport/test/turn_unittest.cpp | 24 +- .../mtransport/third_party/nICEr/IMPORT_FILES | 2 + media/mtransport/third_party/nICEr/nicer.gyp | 2 + .../third_party/nICEr/src/ice/ice_candidate.c | 24 +- .../third_party/nICEr/src/ice/ice_component.c | 44 ++ .../third_party/nICEr/src/ice/ice_component.h | 1 + .../nICEr/src/ice/ice_media_stream.c | 37 +- .../third_party/nICEr/src/ice/ice_parser.c | 15 +- .../nICEr/src/net/nr_proxy_tunnel.c | 2 +- .../third_party/nICEr/src/net/nr_resolver.h | 1 + .../nICEr/src/net/transport_addr.c | 127 ++-- .../nICEr/src/net/transport_addr.h | 7 +- .../nICEr/src/net/transport_addr_reg.c | 62 +- .../third_party/nICEr/src/stun/addrs.c | 570 +++--------------- .../third_party/nICEr/src/stun/addrs.h | 4 +- .../nICEr/src/stun/ifaddrs-android.c | 242 ++++++++ .../nICEr/src/stun/ifaddrs-android.h | 57 ++ .../third_party/nICEr/src/stun/stun_codec.c | 29 +- .../third_party/nICEr/src/stun/stun_reg.h | 1 + .../third_party/nICEr/src/stun/stun_util.c | 34 +- .../third_party/nICEr/src/stun/stun_util.h | 2 +- .../third_party/nrappkit/src/util/util.c | 25 + .../third_party/nrappkit/src/util/util.h | 1 + .../src/peerconnection/PeerConnectionImpl.cpp | 4 +- .../src/peerconnection/PeerConnectionImpl.h | 6 + .../peerconnection/PeerConnectionMedia.cpp | 6 +- .../src/peerconnection/PeerConnectionMedia.h | 6 - .../signaling/src/sdp/SdpMediaSection.h | 5 + .../signaling/test/signaling_unittests.cpp | 3 +- modules/libpref/init/all.js | 1 + 46 files changed, 1064 insertions(+), 792 deletions(-) create mode 100644 media/mtransport/third_party/nICEr/src/stun/ifaddrs-android.c create mode 100644 media/mtransport/third_party/nICEr/src/stun/ifaddrs-android.h diff --git a/media/mtransport/gonk_addrs.cpp b/media/mtransport/gonk_addrs.cpp index 836f24dc71b..d4cd0615d21 100644 --- a/media/mtransport/gonk_addrs.cpp +++ b/media/mtransport/gonk_addrs.cpp @@ -119,7 +119,7 @@ GetInterfaces(std::vector* aInterfaces) int nr_stun_get_addrs(nr_local_addr aAddrs[], int aMaxAddrs, - int aDropLoopback, int* aCount) + int aDropLoopback, int aDropLinkLocal, int* aCount) { nsresult rv; int r; @@ -141,7 +141,6 @@ nr_stun_get_addrs(nr_local_addr aAddrs[], int aMaxAddrs, for (size_t i = 0; i < num_interface; ++i) { NetworkInterface &interface = interfaces[i]; if (nr_sockaddr_to_transport_addr((sockaddr*)&(interface.addr), - sizeof(struct sockaddr_in), IPPROTO_UDP, 0, &(aAddrs[n].addr))) { r_log(NR_LOG_STUN, LOG_WARNING, "Problem transforming address"); return R_FAILED; @@ -154,7 +153,7 @@ nr_stun_get_addrs(nr_local_addr aAddrs[], int aMaxAddrs, } *aCount = n; - r = nr_stun_remove_duplicate_addrs(aAddrs, aDropLoopback, aCount); + r = nr_stun_remove_duplicate_addrs(aAddrs, aDropLoopback, aDropLinkLocal, aCount); if (r != 0) { return r; } diff --git a/media/mtransport/nr_socket_prsock.cpp b/media/mtransport/nr_socket_prsock.cpp index a01befcd662..0b82478b9bb 100644 --- a/media/mtransport/nr_socket_prsock.cpp +++ b/media/mtransport/nr_socket_prsock.cpp @@ -337,20 +337,11 @@ static int nr_transport_addr_to_praddr(nr_transport_addr *addr, naddr->inet.ip = addr->u.addr4.sin_addr.s_addr; break; case NR_IPV6: -#if 0 naddr->ipv6.family = PR_AF_INET6; naddr->ipv6.port = addr->u.addr6.sin6_port; -#ifdef LINUX - memcpy(naddr->ipv6.ip._S6_un._S6_u8, - &addr->u.addr6.sin6_addr.__in6_u.__u6_addr8, 16); -#else - memcpy(naddr->ipv6.ip._S6_un._S6_u8, - &addr->u.addr6.sin6_addr.__u6_addr.__u6_addr8, 16); -#endif -#else - // TODO: make IPv6 work - ABORT(R_INTERNAL); -#endif + naddr->ipv6.flowinfo = addr->u.addr6.sin6_flowinfo; + memcpy(&naddr->ipv6.ip, &addr->u.addr6.sin6_addr, sizeof(in6_addr)); + naddr->ipv6.scope_id = addr->u.addr6.sin6_scope_id; break; default: ABORT(R_BAD_ARGS); @@ -440,6 +431,7 @@ int nr_praddr_to_transport_addr(const PRNetAddr *praddr, int _status; int r; struct sockaddr_in ip4; + struct sockaddr_in6 ip6; switch(praddr->raw.family) { case PR_AF_INET: @@ -447,18 +439,19 @@ int nr_praddr_to_transport_addr(const PRNetAddr *praddr, ip4.sin_addr.s_addr = praddr->inet.ip; ip4.sin_port = praddr->inet.port; if ((r = nr_sockaddr_to_transport_addr((sockaddr *)&ip4, - sizeof(ip4), protocol, keep, addr))) ABORT(r); break; case PR_AF_INET6: -#if 0 - r = nr_sockaddr_to_transport_addr((sockaddr *)&praddr->raw, - sizeof(struct sockaddr_in6),IPPROTO_UDP,keep,addr); + ip6.sin6_family = PF_INET6; + ip6.sin6_port = praddr->ipv6.port; + ip6.sin6_flowinfo = praddr->ipv6.flowinfo; + memcpy(&ip6.sin6_addr, &praddr->ipv6.ip, sizeof(in6_addr)); + ip6.sin6_scope_id = praddr->ipv6.scope_id; + if ((r = nr_sockaddr_to_transport_addr((sockaddr *)&ip6,protocol,keep,addr))) + ABORT(r); break; -#endif - ABORT(R_BAD_ARGS); default: MOZ_ASSERT(false); ABORT(R_BAD_ARGS); @@ -516,14 +509,16 @@ int NrSocket::create(nr_transport_addr *addr) { switch (addr->protocol) { case IPPROTO_UDP: - if (!(fd_ = PR_NewUDPSocket())) { - r_log(LOG_GENERIC,LOG_CRIT,"Couldn't create socket"); + if (!(fd_ = PR_OpenUDPSocket(naddr.raw.family))) { + r_log(LOG_GENERIC,LOG_CRIT,"Couldn't create UDP socket, " + "family=%d, err=%d", naddr.raw.family, PR_GetError()); ABORT(R_INTERNAL); } break; case IPPROTO_TCP: - if (!(fd_ = PR_NewTCPSocket())) { - r_log(LOG_GENERIC,LOG_CRIT,"Couldn't create socket"); + if (!(fd_ = PR_OpenTCPSocket(naddr.raw.family))) { + r_log(LOG_GENERIC,LOG_CRIT,"Couldn't create TCP socket, " + "family=%d, err=%d", naddr.raw.family, PR_GetError()); ABORT(R_INTERNAL); } // Set ReuseAddr for TCP sockets to enable having several @@ -686,7 +681,8 @@ int NrSocket::sendto(const void *msg, size_t len, if (PR_GetError() == PR_WOULD_BLOCK_ERROR) ABORT(R_WOULDBLOCK); - r_log(LOG_GENERIC, LOG_INFO, "Error in sendto: %s", to->as_string); + r_log(LOG_GENERIC, LOG_INFO, "Error in sendto %s: %d", + to->as_string, PR_GetError()); ABORT(R_IO_ERROR); } diff --git a/media/mtransport/nricectx.cpp b/media/mtransport/nricectx.cpp index 8fdae5451cb..729d86a9496 100644 --- a/media/mtransport/nricectx.cpp +++ b/media/mtransport/nricectx.cpp @@ -380,7 +380,8 @@ RefPtr NrIceCtx::Create(const std::string& name, bool offerer, bool set_interface_priorities, bool allow_loopback, - bool tcp_enabled) { + bool tcp_enabled, + bool allow_link_local) { RefPtr ctx = new NrIceCtx(name, offerer); @@ -472,6 +473,10 @@ RefPtr NrIceCtx::Create(const std::string& name, if (allow_loopback) { NR_reg_set_char((char *)NR_STUN_REG_PREF_ALLOW_LOOPBACK_ADDRS, 1); } + + if (allow_link_local) { + NR_reg_set_char((char *)NR_STUN_REG_PREF_ALLOW_LINK_LOCAL_ADDRS, 1); + } } // Create the ICE context diff --git a/media/mtransport/nricectx.h b/media/mtransport/nricectx.h index dbd04af5036..1084d7a30bd 100644 --- a/media/mtransport/nricectx.h +++ b/media/mtransport/nricectx.h @@ -212,7 +212,8 @@ class NrIceCtx { bool offerer, bool set_interface_priorities = true, bool allow_loopback = false, - bool tcp_enabled = true); + bool tcp_enabled = true, + bool allow_link_local = false); // Deinitialize all ICE global state. Used only for testing. static void internal_DeinitializeGlobal(); diff --git a/media/mtransport/nriceresolver.cpp b/media/mtransport/nriceresolver.cpp index d4912cfca2e..f5e74eec2b3 100644 --- a/media/mtransport/nriceresolver.cpp +++ b/media/mtransport/nriceresolver.cpp @@ -150,6 +150,7 @@ int NrIceResolver::resolve(nr_resolver_resource *resource, MOZ_ASSERT(allocated_resolvers_ > 0); ASSERT_ON_THREAD(sts_thread_); nsRefPtr pr; + uint32_t resolve_flags = 0; if (resource->transport_protocol != IPPROTO_UDP && resource->transport_protocol != IPPROTO_TCP) { @@ -162,8 +163,20 @@ int NrIceResolver::resolve(nr_resolver_resource *resource, resource->transport_protocol : IPPROTO_UDP, cb, cb_arg); + + switch(resource->address_family) { + case AF_INET: + resolve_flags |= nsIDNSService::RESOLVE_DISABLE_IPV6; + break; + case AF_INET6: + resolve_flags |= nsIDNSService::RESOLVE_DISABLE_IPV4; + break; + default: + ABORT(R_BAD_ARGS); + } + if (NS_FAILED(dns_->AsyncResolve(nsAutoCString(resource->domain_name), - nsIDNSService::RESOLVE_DISABLE_IPV6, pr, + resolve_flags, pr, sts_thread_, getter_AddRefs(pr->request_)))) { MOZ_MTLOG(ML_ERROR, "AsyncResolve failed."); ABORT(R_NOT_FOUND); diff --git a/media/mtransport/nriceresolverfake.cpp b/media/mtransport/nriceresolverfake.cpp index ead5787d468..94a52fd3c70 100644 --- a/media/mtransport/nriceresolverfake.cpp +++ b/media/mtransport/nriceresolverfake.cpp @@ -122,6 +122,7 @@ int NrIceResolverFake::resolve(void *obj, resource->transport_protocol ? resource->transport_protocol : IPPROTO_UDP, + resource->address_family, cb, cb_arg); if ((r=NR_ASYNC_TIMER_SET(fake->delay_ms_,NrIceResolverFake::resolve_cb, @@ -140,7 +141,8 @@ void NrIceResolverFake::resolve_cb(NR_SOCKET s, int how, void *cb_arg) { MOZ_ASSERT(cb_arg); PendingResolution *pending = static_cast(cb_arg); - const PRNetAddr *addr=pending->resolver_->Resolve(pending->hostname_); + const PRNetAddr *addr=pending->resolver_->Resolve(pending->hostname_, + pending->address_family_); if (addr) { nr_transport_addr transport_addr; diff --git a/media/mtransport/nriceresolverfake.h b/media/mtransport/nriceresolverfake.h index 006e1fe4b90..a37811fc980 100644 --- a/media/mtransport/nriceresolverfake.h +++ b/media/mtransport/nriceresolverfake.h @@ -63,7 +63,16 @@ class NrIceResolverFake { ~NrIceResolverFake(); void SetAddr(const std::string& hostname, const PRNetAddr& addr) { - addrs_[hostname] = addr; + switch (addr.raw.family) { + case AF_INET: + addrs_[hostname] = addr; + break; + case AF_INET6: + addrs6_[hostname] = addr; + break; + default: + MOZ_CRASH(); + } } nr_resolver *AllocateResolver(); @@ -83,11 +92,21 @@ private: static int cancel(void *obj, void *handle); // Get an address. - const PRNetAddr *Resolve(const std::string& hostname) { - if (!addrs_.count(hostname)) - return nullptr; + const PRNetAddr *Resolve(const std::string& hostname, int address_family) { + switch (address_family) { + case AF_INET: + if (!addrs_.count(hostname)) + return nullptr; - return &addrs_[hostname]; + return &addrs_[hostname]; + case AF_INET6: + if (!addrs6_.count(hostname)) + return nullptr; + + return &addrs6_[hostname]; + default: + MOZ_CRASH(); + } } @@ -96,18 +115,21 @@ private: const std::string& hostname, uint16_t port, int transport, + int address_family, int (*cb)(void *cb_arg, nr_transport_addr *addr), void *cb_arg) : resolver_(resolver), hostname_(hostname), port_(port), transport_(transport), + address_family_(address_family), cb_(cb), cb_arg_(cb_arg) {} NrIceResolverFake *resolver_; std::string hostname_; uint16_t port_; int transport_; + int address_family_; int (*cb_)(void *cb_arg, nr_transport_addr *addr); void *cb_arg_; void *timer_handle_; @@ -115,6 +137,7 @@ private: nr_resolver_vtbl* vtbl_; std::map addrs_; + std::map addrs6_; uint32_t delay_ms_; int allocated_resolvers_; }; diff --git a/media/mtransport/nrinterfaceprioritizer.cpp b/media/mtransport/nrinterfaceprioritizer.cpp index 96fc0395e17..a20cfcb915e 100644 --- a/media/mtransport/nrinterfaceprioritizer.cpp +++ b/media/mtransport/nrinterfaceprioritizer.cpp @@ -18,7 +18,8 @@ public: : key_(), is_vpn_(-1), estimated_speed_(-1), - type_preference_(-1) {} + type_preference_(-1), + ip_version_(-1) {} bool Init(const nr_local_addr& local_addr) { char buf[MAXIFNAME + 41]; @@ -31,6 +32,7 @@ public: is_vpn_ = (local_addr.interface.type & NR_INTERFACE_TYPE_VPN) != 0 ? 1 : 0; estimated_speed_ = local_addr.interface.estimated_speed; type_preference_ = GetNetworkTypePreference(local_addr.interface.type); + ip_version_ = local_addr.addr.ip_version; return true; } @@ -54,6 +56,11 @@ public: return estimated_speed_ > rhs.estimated_speed_; } + // Prefer IPV6 over IPV4 + if (ip_version_ != rhs.ip_version_) { + return ip_version_ > rhs.ip_version_; + } + // All things above are the same, we can at least sort with key. return key_ < rhs.key_; } @@ -82,6 +89,7 @@ private: int is_vpn_; int estimated_speed_; int type_preference_; + int ip_version_; }; class InterfacePrioritizer { diff --git a/media/mtransport/stun_udp_socket_filter.cpp b/media/mtransport/stun_udp_socket_filter.cpp index 2c669c2ed70..d5dc8bd017f 100644 --- a/media/mtransport/stun_udp_socket_filter.cpp +++ b/media/mtransport/stun_udp_socket_filter.cpp @@ -21,42 +21,51 @@ extern "C" { namespace { -class NetAddressAdapter { +class NetAddrCompare { public: - MOZ_IMPLICIT NetAddressAdapter(const mozilla::net::NetAddr& netaddr) - : addr_(ntohl(netaddr.inet.ip)), - port_(ntohs(netaddr.inet.port)) { - MOZ_ASSERT(netaddr.raw.family == AF_INET); - } + bool operator()(const mozilla::net::NetAddr& lhs, + const mozilla::net::NetAddr& rhs) const { + if (lhs.raw.family != rhs.raw.family) { + return lhs.raw.family < rhs.raw.family; + } - bool operator<(const NetAddressAdapter& rhs) const { - return addr_ != rhs.addr_ ? (addr_ < rhs.addr_) : (port_ < rhs.port_); - } - - bool operator!=(const NetAddressAdapter& rhs) const { - return (*this < rhs) || (rhs < *this); - } - - private: - const uint32_t addr_; - const uint16_t port_; + switch (lhs.raw.family) { + case AF_INET: + if (lhs.inet.port != rhs.inet.port) { + return lhs.inet.port < rhs.inet.port; + } + return lhs.inet.ip < rhs.inet.ip; + case AF_INET6: + if (lhs.inet6.port != rhs.inet6.port) { + return lhs.inet6.port < rhs.inet6.port; + } + return memcmp(&lhs.inet6.ip, &rhs.inet6.ip, sizeof(lhs.inet6.ip)) < 0; + default: + MOZ_ASSERT(false); + } + return false; + } }; class PendingSTUNRequest { public: - PendingSTUNRequest(const NetAddressAdapter& netaddr, const UINT12 &id) + PendingSTUNRequest(const mozilla::net::NetAddr& netaddr, const UINT12 &id) : id_(id), net_addr_(netaddr), is_id_set_(true) {} - MOZ_IMPLICIT PendingSTUNRequest(const NetAddressAdapter& netaddr) + MOZ_IMPLICIT PendingSTUNRequest(const mozilla::net::NetAddr& netaddr) : id_(), net_addr_(netaddr), is_id_set_(false) {} bool operator<(const PendingSTUNRequest& rhs) const { - if (net_addr_ != rhs.net_addr_) { - return net_addr_ < rhs.net_addr_; + if (NetAddrCompare()(net_addr_, rhs.net_addr_)) { + return true; + } + + if (NetAddrCompare()(rhs.net_addr_, net_addr_)) { + return false; } if (!is_id_set_ && !rhs.is_id_set_) { @@ -76,7 +85,7 @@ class PendingSTUNRequest { private: const UINT12 id_; - const NetAddressAdapter net_addr_; + const mozilla::net::NetAddr net_addr_; const bool is_id_set_; }; @@ -101,7 +110,7 @@ class STUNUDPSocketFilter : public nsIUDPSocketFilter { const uint8_t *data, uint32_t len); - std::set white_list_; + std::set white_list_; std::set pending_requests_; std::set response_allowed_; }; @@ -114,12 +123,6 @@ STUNUDPSocketFilter::FilterPacket(const mozilla::net::NetAddr *remote_addr, uint32_t len, int32_t direction, bool *result) { - // Allowing IPv4 address only. - if (remote_addr->raw.family != AF_INET) { - *result = false; - return NS_OK; - } - switch (direction) { case nsIUDPSocketFilter::SF_INCOMING: *result = filter_incoming_packet(remote_addr, data, len); diff --git a/media/mtransport/test/buffered_stun_socket_unittest.cpp b/media/mtransport/test/buffered_stun_socket_unittest.cpp index ccac5b62cb1..40e9e31b486 100644 --- a/media/mtransport/test/buffered_stun_socket_unittest.cpp +++ b/media/mtransport/test/buffered_stun_socket_unittest.cpp @@ -64,7 +64,7 @@ class BufferedStunSocketTest : public ::testing::Test { ASSERT_EQ(0, r); dummy_ = dummy.forget(); // Now owned by test_socket_. - r = nr_ip4_str_port_to_transport_addr( + r = nr_str_port_to_transport_addr( (char *)"192.0.2.133", 3333, IPPROTO_TCP, &remote_addr_); ASSERT_EQ(0, r); @@ -184,7 +184,7 @@ TEST_F(BufferedStunSocketTest, TestSendToReject) { TEST_F(BufferedStunSocketTest, TestSendToWrongAddr) { nr_transport_addr addr; - int r = nr_ip4_str_port_to_transport_addr( + int r = nr_str_port_to_transport_addr( (char *)"192.0.2.134", 3333, IPPROTO_TCP, &addr); ASSERT_EQ(0, r); diff --git a/media/mtransport/test/ice_unittest.cpp b/media/mtransport/test/ice_unittest.cpp index c86337db8a6..47211229a17 100644 --- a/media/mtransport/test/ice_unittest.cpp +++ b/media/mtransport/test/ice_unittest.cpp @@ -354,8 +354,8 @@ class IceTestPeer : public sigslot::has_slots<> { } void UseTestStunServer() { - SetStunServer(TestStunServer::GetInstance()->addr(), - TestStunServer::GetInstance()->port()); + SetStunServer(TestStunServer::GetInstance(AF_INET)->addr(), + TestStunServer::GetInstance(AF_INET)->port()); } void SetTurnServer(const std::string addr, uint16_t port, @@ -382,15 +382,15 @@ class IceTestPeer : public sigslot::has_slots<> { ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetTurnServers(servers))); } - void SetFakeResolver() { + void SetFakeResolver(const std::string& ip = g_stun_server_address, + const std::string& fqdn = g_stun_server_hostname) { ASSERT_TRUE(NS_SUCCEEDED(dns_resolver_->Init())); - if (!g_stun_server_address.empty() && !g_stun_server_hostname.empty()) { + if (!ip.empty() && !fqdn.empty()) { PRNetAddr addr; - PRStatus status = PR_StringToNetAddr(g_stun_server_address.c_str(), - &addr); + PRStatus status = PR_StringToNetAddr(ip.c_str(), &addr); addr.inet.port = kDefaultStunServerPort; ASSERT_EQ(PR_SUCCESS, status); - fake_resolver_.SetAddr(g_stun_server_hostname, addr); + fake_resolver_.SetAddr(fqdn, addr); } ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetResolver( fake_resolver_.AllocateResolver()))); @@ -1098,9 +1098,16 @@ void SchedulableTrickleCandidate::Trickle() { class IceGatherTest : public ::testing::Test { public: void SetUp() { - test_utils->sts_target()->Dispatch(WrapRunnable(TestStunServer::GetInstance(), - &TestStunServer::Reset), - NS_DISPATCH_SYNC); + test_utils->sts_target()->Dispatch( + WrapRunnable(TestStunServer::GetInstance(AF_INET), + &TestStunServer::Reset), + NS_DISPATCH_SYNC); + if (TestStunServer::GetInstance(AF_INET6)) { + test_utils->sts_target()->Dispatch( + WrapRunnable(TestStunServer::GetInstance(AF_INET6), + &TestStunServer::Reset), + NS_DISPATCH_SYNC); + } } void TearDown() { @@ -1135,54 +1142,90 @@ class IceGatherTest : public ::testing::Test { ASSERT_TRUE_WAIT(peer_->gathering_complete(), waitTime); } - void UseFakeStunUdpServerWithResponse(const std::string& fake_addr, - uint16_t fake_port) { - EnsurePeer(); - TestStunServer::GetInstance()->SetResponseAddr(fake_addr, fake_port); - // Sets an additional stun server - peer_->SetStunServer(TestStunServer::GetInstance()->addr(), - TestStunServer::GetInstance()->port(), - kNrIceTransportUdp); + void AddStunServerWithResponse( + const std::string& fake_addr, + uint16_t fake_port, + const std::string& fqdn, + const std::string& proto, + std::vector* stun_servers) { + int family; + if (fake_addr.find(':') != std::string::npos) { + family = AF_INET6; + } else { + family = AF_INET; + } + + std::string stun_addr; + uint16_t stun_port; + if (proto == kNrIceTransportUdp) { + TestStunServer::GetInstance(family)->SetResponseAddr(fake_addr, + fake_port); + stun_addr = TestStunServer::GetInstance(family)->addr(); + stun_port = TestStunServer::GetInstance(family)->port(); + } else if (proto == kNrIceTransportTcp) { + TestStunTcpServer::GetInstance(family)->SetResponseAddr(fake_addr, + fake_port); + stun_addr = TestStunTcpServer::GetInstance(family)->addr(); + stun_port = TestStunTcpServer::GetInstance(family)->port(); + } else { + MOZ_CRASH(); + } + + if (!fqdn.empty()) { + peer_->SetFakeResolver(stun_addr, fqdn); + stun_addr = fqdn; + } + + stun_servers->push_back(*NrIceStunServer::Create(stun_addr, + stun_port, + proto.c_str())); } - void UseFakeStunTcpServerWithResponse(const std::string& fake_addr, - uint16_t fake_port) { - EnsurePeer(); - TestStunTcpServer::GetInstance()->SetResponseAddr(fake_addr, fake_port); - // Sets an additional stun server - peer_->SetStunServer(TestStunTcpServer::GetInstance()->addr(), - TestStunTcpServer::GetInstance()->port(), - kNrIceTransportTcp); - } - - void UseFakeStunUdpTcpServersWithResponse(const std::string& fake_udp_addr, - uint16_t fake_udp_port, - const std::string& fake_tcp_addr, - uint16_t fake_tcp_port) { + void UseFakeStunUdpServerWithResponse( + const std::string& fake_addr, + uint16_t fake_port, + const std::string& fqdn = std::string()) { EnsurePeer(); std::vector stun_servers; + AddStunServerWithResponse(fake_addr, fake_port, fqdn, "udp", &stun_servers); + peer_->SetStunServers(stun_servers); + } - stun_servers.push_back(*NrIceStunServer::Create( - TestStunServer::GetInstance()->addr(), - TestStunServer::GetInstance()->port(), - kNrIceTransportUdp)); - stun_servers.push_back(*NrIceStunServer::Create( - TestStunTcpServer::GetInstance()->addr(), - TestStunTcpServer::GetInstance()->port(), - kNrIceTransportTcp)); + void UseFakeStunTcpServerWithResponse( + const std::string& fake_addr, + uint16_t fake_port, + const std::string& fqdn = std::string()) { + EnsurePeer(); + std::vector stun_servers; + AddStunServerWithResponse(fake_addr, fake_port, fqdn, "tcp", &stun_servers); + peer_->SetStunServers(stun_servers); + } + + void UseFakeStunUdpTcpServersWithResponse( + const std::string& fake_udp_addr, + uint16_t fake_udp_port, + const std::string& fake_tcp_addr, + uint16_t fake_tcp_port) { + EnsurePeer(); + std::vector stun_servers; + AddStunServerWithResponse(fake_udp_addr, + fake_udp_port, + "", // no fqdn + "udp", + &stun_servers); + AddStunServerWithResponse(fake_tcp_addr, + fake_tcp_port, + "", // no fqdn + "tcp", + &stun_servers); - TestStunServer::GetInstance()->SetResponseAddr(fake_udp_addr, - fake_udp_port); - TestStunTcpServer::GetInstance()->SetResponseAddr(fake_tcp_addr, - fake_tcp_port); - // Sets an additional stun server peer_->SetStunServers(stun_servers); } void UseTestStunServer() { - TestStunServer::GetInstance()->Reset(); - peer_->SetStunServer(TestStunServer::GetInstance()->addr(), - TestStunServer::GetInstance()->port()); + TestStunServer::GetInstance(AF_INET)->Reset(); + peer_->SetStunServer(TestStunServer::GetInstance(AF_INET)->addr(), + TestStunServer::GetInstance(AF_INET)->port()); } // NB: Only does substring matching, watch out for stuff like "1.2.3.4" @@ -1314,7 +1357,7 @@ class IceConnectTest : public ::testing::Test { } void UseTestStunServer() { - TestStunServer::GetInstance()->Reset(); + TestStunServer::GetInstance(AF_INET)->Reset(); p1_->UseTestStunServer(); p2_->UseTestStunServer(); } @@ -1482,8 +1525,8 @@ class PrioritizerTest : public ::testing::Test { local_addr.interface.type = type; local_addr.interface.estimated_speed = estimated_speed; - int r = nr_ip4_str_port_to_transport_addr(str_addr.c_str(), 0, - IPPROTO_UDP, &(local_addr.addr)); + int r = nr_str_port_to_transport_addr(str_addr.c_str(), 0, + IPPROTO_UDP, &(local_addr.addr)); ASSERT_EQ(0, r); strncpy(local_addr.addr.ifname, ifname.c_str(), MAXIFNAME); @@ -1791,12 +1834,48 @@ TEST_F(IceGatherTest, VerifyTestStunTcpServer) { " tcptype ")); } +TEST_F(IceGatherTest, VerifyTestStunServerV6) { + if (!TestStunServer::GetInstance(AF_INET6)) { + // No V6 addresses + return; + } + UseFakeStunUdpServerWithResponse("beef::", 3333); + Gather(); + ASSERT_TRUE(StreamHasMatchingCandidate(0, " beef:: 3333 ")); +} + +TEST_F(IceGatherTest, VerifyTestStunServerFQDN) { + UseFakeStunUdpServerWithResponse("192.0.2.133", 3333, "stun.example.com"); + Gather(); + ASSERT_TRUE(StreamHasMatchingCandidate(0, " 192.0.2.133 3333 ")); +} + +TEST_F(IceGatherTest, VerifyTestStunServerV6FQDN) { + if (!TestStunServer::GetInstance(AF_INET6)) { + // No V6 addresses + return; + } + UseFakeStunUdpServerWithResponse("beef::", 3333, "stun.example.com"); + Gather(); + ASSERT_TRUE(StreamHasMatchingCandidate(0, " beef:: 3333 ")); +} + TEST_F(IceGatherTest, TestStunServerReturnsWildcardAddr) { UseFakeStunUdpServerWithResponse("0.0.0.0", 3333); Gather(kDefaultTimeout * 3); ASSERT_FALSE(StreamHasMatchingCandidate(0, " 0.0.0.0 ")); } +TEST_F(IceGatherTest, TestStunServerReturnsWildcardAddrV6) { + if (!TestStunServer::GetInstance(AF_INET6)) { + // No V6 addresses + return; + } + UseFakeStunUdpServerWithResponse("::", 3333); + Gather(kDefaultTimeout * 3); + ASSERT_FALSE(StreamHasMatchingCandidate(0, " :: ")); +} + TEST_F(IceGatherTest, TestStunServerReturnsPort0) { UseFakeStunUdpServerWithResponse("192.0.2.133", 0); Gather(kDefaultTimeout * 3); @@ -1809,35 +1888,45 @@ TEST_F(IceGatherTest, TestStunServerReturnsLoopbackAddr) { ASSERT_FALSE(StreamHasMatchingCandidate(0, " 127.0.0.133 ")); } +TEST_F(IceGatherTest, TestStunServerReturnsLoopbackAddrV6) { + if (!TestStunServer::GetInstance(AF_INET6)) { + // No V6 addresses + return; + } + UseFakeStunUdpServerWithResponse("::1", 3333); + Gather(kDefaultTimeout * 3); + ASSERT_FALSE(StreamHasMatchingCandidate(0, " ::1 ")); +} + TEST_F(IceGatherTest, TestStunServerTrickle) { UseFakeStunUdpServerWithResponse("192.0.2.1", 3333); - TestStunServer::GetInstance()->SetActive(false); + TestStunServer::GetInstance(AF_INET)->SetActive(false); Gather(0); ASSERT_FALSE(StreamHasMatchingCandidate(0, "192.0.2.1")); - TestStunServer::GetInstance()->SetActive(true); + TestStunServer::GetInstance(AF_INET)->SetActive(true); WaitForGather(); ASSERT_TRUE(StreamHasMatchingCandidate(0, "192.0.2.1")); } TEST_F(IceGatherTest, TestStunTcpServerTrickle) { UseFakeStunTcpServerWithResponse("192.0.3.1", 3333); - TestStunTcpServer::GetInstance()->SetActive(false); + TestStunTcpServer::GetInstance(AF_INET)->SetActive(false); Gather(0); ASSERT_FALSE(StreamHasMatchingCandidate(0, " 192.0.3.1 ", " tcptype ")); - TestStunTcpServer::GetInstance()->SetActive(true); + TestStunTcpServer::GetInstance(AF_INET)->SetActive(true); WaitForGather(); ASSERT_TRUE(StreamHasMatchingCandidate(0, " 192.0.3.1 ", " tcptype ")); } TEST_F(IceGatherTest, TestStunTcpAndUdpServerTrickle) { UseFakeStunUdpTcpServersWithResponse("192.0.2.1", 3333, "192.0.3.1", 3333); - TestStunServer::GetInstance()->SetActive(false); - TestStunTcpServer::GetInstance()->SetActive(false); + TestStunServer::GetInstance(AF_INET)->SetActive(false); + TestStunTcpServer::GetInstance(AF_INET)->SetActive(false); Gather(0); ASSERT_FALSE(StreamHasMatchingCandidate(0, "192.0.2.1", "UDP")); ASSERT_FALSE(StreamHasMatchingCandidate(0, " 192.0.3.1 ", " tcptype ")); - TestStunServer::GetInstance()->SetActive(true); - TestStunTcpServer::GetInstance()->SetActive(true); + TestStunServer::GetInstance(AF_INET)->SetActive(true); + TestStunTcpServer::GetInstance(AF_INET)->SetActive(true); WaitForGather(); ASSERT_TRUE(StreamHasMatchingCandidate(0, "192.0.2.1", "UDP")); ASSERT_TRUE(StreamHasMatchingCandidate(0, " 192.0.3.1 ", " tcptype ")); @@ -2863,10 +2952,18 @@ int main(int argc, char **argv) listeners.Append(new test::RingbufferDumper(test_utils)); test_utils->sts_target()->Dispatch( - WrapRunnableNM(&TestStunServer::GetInstance), NS_DISPATCH_SYNC); + WrapRunnableNM(&TestStunServer::GetInstance, AF_INET), + NS_DISPATCH_SYNC); + test_utils->sts_target()->Dispatch( + WrapRunnableNM(&TestStunServer::GetInstance, AF_INET6), + NS_DISPATCH_SYNC); test_utils->sts_target()->Dispatch( - WrapRunnableNM(&TestStunTcpServer::GetInstance), NS_DISPATCH_SYNC); + WrapRunnableNM(&TestStunTcpServer::GetInstance, AF_INET), + NS_DISPATCH_SYNC); + test_utils->sts_target()->Dispatch( + WrapRunnableNM(&TestStunTcpServer::GetInstance, AF_INET6), + NS_DISPATCH_SYNC); int rv = RUN_ALL_TESTS(); diff --git a/media/mtransport/test/multi_tcp_socket_unittest.cpp b/media/mtransport/test/multi_tcp_socket_unittest.cpp index cd4291826df..bc6535ab3d6 100644 --- a/media/mtransport/test/multi_tcp_socket_unittest.cpp +++ b/media/mtransport/test/multi_tcp_socket_unittest.cpp @@ -112,7 +112,7 @@ class MultiTcpSocketTest : public ::testing::Test { r = 1; for (int tries=10; tries && r; --tries) { - r = nr_ip4_str_port_to_transport_addr( + r = nr_str_port_to_transport_addr( (char *)"127.0.0.1", EnsureEphemeral(port_s++), IPPROTO_TCP, &local); ASSERT_EQ(0, r); diff --git a/media/mtransport/test/proxy_tunnel_socket_unittest.cpp b/media/mtransport/test/proxy_tunnel_socket_unittest.cpp index 7a7ba843e3e..2705af3b739 100644 --- a/media/mtransport/test/proxy_tunnel_socket_unittest.cpp +++ b/media/mtransport/test/proxy_tunnel_socket_unittest.cpp @@ -84,7 +84,7 @@ class DummyResolver { void **handle) { nr_transport_addr addr; - nr_ip4_str_port_to_transport_addr( + nr_str_port_to_transport_addr( (char *)kProxyAddr.c_str(), kProxyPort, IPPROTO_TCP, &addr); cb(cb_arg, &addr); @@ -120,11 +120,11 @@ class ProxyTunnelSocketTest : public ::testing::Test { nr_resolver_ = resolver_impl_.get_nr_resolver(); - int r = nr_ip4_str_port_to_transport_addr( + int r = nr_str_port_to_transport_addr( (char *)kRemoteAddr.c_str(), kRemotePort, IPPROTO_TCP, &remote_addr_); ASSERT_EQ(0, r); - r = nr_ip4_str_port_to_transport_addr( + r = nr_str_port_to_transport_addr( (char *)kProxyAddr.c_str(), kProxyPort, IPPROTO_TCP, &proxy_addr_); ASSERT_EQ(0, r); diff --git a/media/mtransport/test/stunserver.cpp b/media/mtransport/test/stunserver.cpp index 612aedb6bf7..2198c41bb76 100644 --- a/media/mtransport/test/stunserver.cpp +++ b/media/mtransport/test/stunserver.cpp @@ -188,6 +188,8 @@ int nr_socket_wrapped_create(nr_socket *inner, nr_socket **outp) { // we have no reason to expect this will be initted to a nullptr yet. TestStunServer* TestStunServer::instance; TestStunTcpServer* TestStunTcpServer::instance; +TestStunServer* TestStunServer::instance6; +TestStunTcpServer* TestStunTcpServer::instance6; uint16_t TestStunServer::instance_port = 3478; uint16_t TestStunTcpServer::instance_port = 3478; @@ -243,12 +245,14 @@ int TestStunServer::TryOpenListenSocket(nr_local_addr* addr, uint16_t port) { return 0; } -int TestStunServer::Initialize() { - nr_local_addr addrs[100]; +int TestStunServer::Initialize(int address_family) { + static const size_t max_addrs = 100; + nr_local_addr addrs[max_addrs]; int addr_ct; int r; + int i; - r = nr_stun_find_local_addresses(addrs, 100, &addr_ct); + r = nr_stun_find_local_addresses(addrs, max_addrs, &addr_ct); if (r) { MOZ_MTLOG(ML_ERROR, "Couldn't retrieve addresses"); return R_INTERNAL; @@ -259,10 +263,21 @@ int TestStunServer::Initialize() { return R_INTERNAL; } + for (i = 0; i < addr_ct; ++i) { + if (addrs[i].addr.addr->sa_family == address_family) { + break; + } + } + + if (i == addr_ct) { + MOZ_MTLOG(ML_ERROR, "No local addresses of the configured IP version"); + return R_INTERNAL; + } + int tries = 100; while (tries--) { - // Bind to the first address (arbitrarily) on configured port (default 3478) - r = TryOpenListenSocket(&addrs[0], instance_port); + // Bind on configured port (default 3478) + r = TryOpenListenSocket(&addrs[i], instance_port); // We interpret R_ALREADY to mean the addr is probably in use. Try another. // Otherwise, it either worked or it didn't, and we check below. if (r != R_ALREADY) { @@ -291,7 +306,7 @@ int TestStunServer::Initialize() { // Cache the address and port. char addr_string[INET6_ADDRSTRLEN]; - r = nr_transport_addr_get_addrstring(&addrs[0].addr, addr_string, + r = nr_transport_addr_get_addrstring(&addrs[i].addr, addr_string, sizeof(addr_string)); if (r) { MOZ_MTLOG(ML_ERROR, "Failed to convert listen addr to a string representation"); @@ -304,12 +319,12 @@ int TestStunServer::Initialize() { return 0; } -TestStunServer* TestStunServer::Create() { +TestStunServer* TestStunServer::Create(int address_family) { NR_reg_init(NR_REG_MODE_LOCAL); ScopedDeletePtr server(new TestStunServer()); - if (server->Initialize()) + if (server->Initialize(address_family)) return nullptr; NR_SOCKET fd; @@ -328,18 +343,29 @@ void TestStunServer::ConfigurePort(uint16_t port) { instance_port = port; } -TestStunServer* TestStunServer::GetInstance() { - if (!instance) - instance = Create(); +TestStunServer* TestStunServer::GetInstance(int address_family) { + switch (address_family) { + case AF_INET: + if (!instance) + instance = Create(address_family); - MOZ_ASSERT(instance); - return instance; + MOZ_ASSERT(instance); + return instance; + case AF_INET6: + if (!instance6) + instance6 = Create(address_family); + + return instance6; + default: + MOZ_CRASH(); + } } void TestStunServer::ShutdownInstance() { delete instance; - instance = nullptr; + delete instance6; + instance6 = nullptr; } @@ -453,9 +479,9 @@ nsresult TestStunServer::SetResponseAddr(const std::string& addr, uint16_t port) { nr_transport_addr addr2; - int r = nr_ip4_str_port_to_transport_addr(addr.c_str(), - port, IPPROTO_UDP, - &addr2); + int r = nr_str_port_to_transport_addr(addr.c_str(), + port, IPPROTO_UDP, + &addr2); if (r) return NS_ERROR_FAILURE; @@ -479,12 +505,22 @@ void TestStunTcpServer::ConfigurePort(uint16_t port) { instance_port = port; } -TestStunTcpServer* TestStunTcpServer::GetInstance() { - if (!instance) - instance = Create(); +TestStunTcpServer* TestStunTcpServer::GetInstance(int address_family) { + switch (address_family) { + case AF_INET: + if (!instance) + instance = Create(address_family); - MOZ_ASSERT(instance); - return instance; + MOZ_ASSERT(instance); + return instance; + case AF_INET6: + if (!instance6) + instance6 = Create(address_family); + + return instance6; + default: + MOZ_CRASH(); + } } void TestStunTcpServer::ShutdownInstance() { @@ -523,12 +559,14 @@ int TestStunTcpServer::TryOpenListenSocket(nr_local_addr* addr, uint16_t port) { return 0; } -TestStunTcpServer* TestStunTcpServer::Create() { +TestStunTcpServer* TestStunTcpServer::Create(int address_family) { NR_reg_init(NR_REG_MODE_LOCAL); ScopedDeletePtr server(new TestStunTcpServer()); - server->Initialize(); + if (server->Initialize(address_family)) { + return nullptr; + } nr_socket_multi_tcp_set_readable_cb(server->listen_sock_, &TestStunServer::readable_cb, server.get()); diff --git a/media/mtransport/test/stunserver.h b/media/mtransport/test/stunserver.h index 6b89af114f7..ad8cfb8b82f 100644 --- a/media/mtransport/test/stunserver.h +++ b/media/mtransport/test/stunserver.h @@ -24,12 +24,13 @@ class TestStunServer { public: // Generally, you should only call API in this class from the same thread that // the initial |GetInstance| call was made from. - static TestStunServer *GetInstance(); + static TestStunServer *GetInstance(int address_family = AF_INET); static void ShutdownInstance(); // |ConfigurePort| will only have an effect if called before the first call // to |GetInstance| (possibly following a |ShutdownInstance| call) static void ConfigurePort(uint16_t port); - static TestStunServer *Create(); + // AF_INET, AF_INET6 + static TestStunServer *Create(int address_family); virtual ~TestStunServer(); @@ -59,7 +60,7 @@ class TestStunServer { timer_handle_(nullptr) {} int SetInternalPort(nr_local_addr* addr, uint16_t port); - int Initialize(); + int Initialize(int address_family); static void readable_cb(NR_SOCKET sock, int how, void *cb_arg); private: @@ -82,12 +83,13 @@ class TestStunServer { std::map received_ct_; static TestStunServer* instance; + static TestStunServer* instance6; static uint16_t instance_port; }; class TestStunTcpServer: public TestStunServer { public: - static TestStunTcpServer *GetInstance(); + static TestStunTcpServer *GetInstance(int address_family); static void ShutdownInstance(); static void ConfigurePort(uint16_t port); virtual ~TestStunTcpServer(); @@ -98,9 +100,10 @@ class TestStunTcpServer: public TestStunServer { nsRefPtr ice_ctx_; private: virtual int TryOpenListenSocket(nr_local_addr* addr, uint16_t port); - static TestStunTcpServer *Create(); + static TestStunTcpServer *Create(int address_family); static TestStunTcpServer* instance; + static TestStunTcpServer* instance6; static uint16_t instance_port; }; } // End of namespace mozilla diff --git a/media/mtransport/test/test_nr_socket_unittest.cpp b/media/mtransport/test/test_nr_socket_unittest.cpp index 2e68553f563..425ec39fb36 100644 --- a/media/mtransport/test/test_nr_socket_unittest.cpp +++ b/media/mtransport/test/test_nr_socket_unittest.cpp @@ -67,7 +67,7 @@ class TestNrSocketTest : public ::testing::Test { // is how we simulate a non-natted socket. nsRefPtr sock(new TestNrSocket(nat ? nat : new TestNat)); nr_transport_addr address; - nr_ip4_str_port_to_transport_addr(ip_str, 0, IPPROTO_UDP, &address); + nr_str_port_to_transport_addr(ip_str, 0, IPPROTO_UDP, &address); int r = sock->create(&address); if (r) { return nullptr; diff --git a/media/mtransport/test/turn_unittest.cpp b/media/mtransport/test/turn_unittest.cpp index 2b624fa60aa..a8103d17372 100644 --- a/media/mtransport/test/turn_unittest.cpp +++ b/media/mtransport/test/turn_unittest.cpp @@ -132,7 +132,7 @@ class TurnClient : public ::testing::Test { net_socket_ = real_socket_; } - r = nr_ip4_str_port_to_transport_addr(turn_server_.c_str(), 3478, + r = nr_str_port_to_transport_addr(turn_server_.c_str(), 3478, protocol_, &addr); ASSERT_EQ(0, r); @@ -237,10 +237,10 @@ class TurnClient : public ::testing::Test { std::string host = target.substr(4, offset - 4); std::string port = target.substr(offset + 1); - r = nr_ip4_str_port_to_transport_addr(host.c_str(), - atoi(port.c_str()), - IPPROTO_UDP, - &addr); + r = nr_str_port_to_transport_addr(host.c_str(), + atoi(port.c_str()), + IPPROTO_UDP, + &addr); ASSERT_EQ(0, r); r = nr_turn_client_ensure_perm(turn_ctx_, &addr); @@ -324,10 +324,10 @@ class TurnClient : public ::testing::Test { std::string host = target.substr(4, offset - 4); std::string port = target.substr(offset + 1); - r = nr_ip4_str_port_to_transport_addr(host.c_str(), - atoi(port.c_str()), - IPPROTO_UDP, - &addr); + r = nr_str_port_to_transport_addr(host.c_str(), + atoi(port.c_str()), + IPPROTO_UDP, + &addr); ASSERT_EQ(0, r); unsigned char test[100]; @@ -488,8 +488,8 @@ int main(int argc, char **argv) } { nr_transport_addr addr; - if (nr_ip4_str_port_to_transport_addr(g_turn_server.c_str(), 3478, - IPPROTO_UDP, &addr)) { + if (nr_str_port_to_transport_addr(g_turn_server.c_str(), 3478, + IPPROTO_UDP, &addr)) { printf("Invalid TURN_SERVER_ADDRESS \"%s\". Only IP numbers supported.\n", g_turn_server.c_str()); return 0; @@ -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), + dummy, false, false, false, false, false), NS_DISPATCH_SYNC); // Start the tests diff --git a/media/mtransport/third_party/nICEr/IMPORT_FILES b/media/mtransport/third_party/nICEr/IMPORT_FILES index 2db3354019d..4b30b214108 100644 --- a/media/mtransport/third_party/nICEr/IMPORT_FILES +++ b/media/mtransport/third_party/nICEr/IMPORT_FILES @@ -37,6 +37,8 @@ # STUN ./src/stun/addrs.c ./src/stun/addrs.h + ./src/stun/ifaddrs-android.c + ./src/stun/ifaddrs-android.h ./src/stun/nr_socket_turn.c ./src/stun/nr_socket_turn.h ./src/stun/stun.h diff --git a/media/mtransport/third_party/nICEr/nicer.gyp b/media/mtransport/third_party/nICEr/nicer.gyp index 590b7b8f2ee..9df4a4b28ef 100644 --- a/media/mtransport/third_party/nICEr/nicer.gyp +++ b/media/mtransport/third_party/nICEr/nicer.gyp @@ -88,6 +88,8 @@ # STUN "./src/stun/addrs.c", "./src/stun/addrs.h", + "./src/stun/ifaddrs-android.c", + "./src/stun/ifaddrs-android.h", "./src/stun/nr_socket_turn.c", "./src/stun/nr_socket_turn.h", "./src/stun/nr_socket_buffered_stun.c", diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_candidate.c b/media/mtransport/third_party/nICEr/src/ice/ice_candidate.c index d23310bc233..7d76b02a024 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_candidate.c +++ b/media/mtransport/third_party/nICEr/src/ice/ice_candidate.c @@ -64,7 +64,7 @@ static char *RCSSTRING __UNUSED__="$Id: ice_candidate.c,v 1.2 2008/04/28 17:59:0 #include "nr_socket.h" #include "nr_socket_multi_tcp.h" -static int next_automatic_preference = 224; +static int next_automatic_preference = 127; static int nr_ice_candidate_initialize2(nr_ice_candidate *cand); static int nr_ice_get_foundation(nr_ice_ctx *ctx,nr_ice_candidate *cand); @@ -470,8 +470,12 @@ int nr_ice_candidate_compute_priority(nr_ice_candidate *cand) if (r=NR_reg_set2_uchar(NR_ICE_REG_PREF_INTERFACE_PRFX,cand->base.ifname,next_automatic_preference)){ ABORT(r); } - interface_preference=next_automatic_preference; + interface_preference=next_automatic_preference << 1; next_automatic_preference--; + if (cand->base.ip_version == NR_IPV6) { + /* Prefer IPV6 over IPV4 on the same interface. */ + interface_preference += 1; + } } else { ABORT(r); @@ -550,6 +554,11 @@ int nr_ice_candidate_initialize(nr_ice_candidate *cand, NR_async_cb ready_cb, vo cand->state=NR_ICE_CAND_STATE_INITIALIZING; if(cand->stun_server->type == NR_ICE_STUN_SERVER_TYPE_ADDR) { + if(cand->base.ip_version != cand->stun_server->u.addr.ip_version) { + r_log(LOG_ICE, LOG_INFO, "ICE-CANDIDATE(%s): Skipping srflx/relayed candidate with different IP version (%d) than STUN/TURN server (%d).", cand->label,cand->base.ip_version,cand->stun_server->u.addr.ip_version); + ABORT(R_NOT_FOUND); /* Same error code when DNS lookup fails */ + } + /* Just copy the address */ if (r=nr_transport_addr_copy(&cand->stun_server_addr, &cand->stun_server->u.addr)) { @@ -567,6 +576,17 @@ int nr_ice_candidate_initialize(nr_ice_candidate *cand, NR_async_cb ready_cb, vo resource.stun_turn=protocol; resource.transport_protocol=cand->stun_server->transport; + switch (cand->base.ip_version) { + case NR_IPV4: + resource.address_family=AF_INET; + break; + case NR_IPV6: + resource.address_family=AF_INET6; + break; + default: + ABORT(R_BAD_ARGS); + } + /* Try to resolve */ if(!cand->ctx->resolver) { r_log(LOG_ICE, LOG_ERR, "ICE-CANDIDATE(%s): Can't use DNS names without a resolver", cand->label); diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_component.c b/media/mtransport/third_party/nICEr/src/ice/ice_component.c index 19c4b01ddc1..6315b466a70 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_component.c +++ b/media/mtransport/third_party/nICEr/src/ice/ice_component.c @@ -999,6 +999,9 @@ int nr_ice_component_pair_candidate(nr_ice_peer_ctx *pctx, nr_ice_component *pco continue; if (lcand->tcp_type == TCP_TYPE_PASSIVE) continue; + if(pcand->addr.ip_version != lcand->addr.ip_version) + continue; + /* Two modes, depending on |pair_all_remote| @@ -1334,3 +1337,44 @@ int nr_ice_component_insert_pair(nr_ice_component *pcomp, nr_ice_cand_pair *pair return(_status); } +int nr_ice_component_get_default_candidate(nr_ice_component *comp, nr_ice_candidate **candp, int ip_version) + { + int _status; + nr_ice_candidate *cand; + nr_ice_candidate *best_cand = NULL; + + /* We have the component. Now find the "best" candidate, making + use of the fact that more "reliable" candidate types have + higher numbers. So, we sort by type and then priority within + type + */ + cand=TAILQ_FIRST(&comp->candidates); + while(cand){ + if (cand->state == NR_ICE_CAND_STATE_INITIALIZED && + cand->addr.ip_version == ip_version) { + if (!best_cand) { + best_cand = cand; + } + else if (best_cand->type < cand->type) { + best_cand = cand; + } else if (best_cand->type == cand->type && + best_cand->priority < cand->priority) { + best_cand = cand; + } + } + + cand=TAILQ_NEXT(cand,entry_comp); + } + + /* No candidates */ + if (!best_cand) + ABORT(R_NOT_FOUND); + + *candp = best_cand; + + _status=0; + abort: + return(_status); + + } + diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_component.h b/media/mtransport/third_party/nICEr/src/ice/ice_component.h index 2bead9fae6c..7fb58368576 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_component.h +++ b/media/mtransport/third_party/nICEr/src/ice/ice_component.h @@ -93,6 +93,7 @@ int nr_ice_component_select_pair(nr_ice_peer_ctx *pctx, nr_ice_component *comp); int nr_ice_component_set_failed(nr_ice_component *comp); int nr_ice_component_finalize(nr_ice_component *lcomp, nr_ice_component *rcomp); int nr_ice_component_insert_pair(nr_ice_component *pcomp, nr_ice_cand_pair *pair); +int nr_ice_component_get_default_candidate(nr_ice_component *comp, nr_ice_candidate **candp, int ip_version); #ifdef __cplusplus } diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_media_stream.c b/media/mtransport/third_party/nICEr/src/ice/ice_media_stream.c index 96a81573ee0..6bb8f994b7b 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_media_stream.c +++ b/media/mtransport/third_party/nICEr/src/ice/ice_media_stream.c @@ -223,14 +223,11 @@ int nr_ice_media_stream_get_attributes(nr_ice_media_stream *stream, char ***attr return(_status); } - /* Get a default candidate per 4.1.4 */ int nr_ice_media_stream_get_default_candidate(nr_ice_media_stream *stream, int component, nr_ice_candidate **candp) { - int _status; + int r,_status; nr_ice_component *comp; - nr_ice_candidate *cand; - nr_ice_candidate *best_cand = NULL; comp=STAILQ_FIRST(&stream->components); while(comp){ @@ -243,36 +240,12 @@ int nr_ice_media_stream_get_default_candidate(nr_ice_media_stream *stream, int c if (!comp) ABORT(R_NOT_FOUND); - /* We have the component. Now find the "best" candidate, making - use of the fact that more "reliable" candidate types have - higher numbers. So, we sort by type and then priority within - type - */ - cand=TAILQ_FIRST(&comp->candidates); - while(cand){ - if (cand->state == NR_ICE_CAND_STATE_INITIALIZED) { - if (!best_cand) { - best_cand = cand; - } - else { - if (best_cand->type < cand->type) { - best_cand = cand; - } else if (best_cand->type == cand->type) { - if (best_cand->priority < cand->priority) - best_cand = cand; - } - } - } - - cand=TAILQ_NEXT(cand,entry_comp); + /* If there aren't any IPV4 candidates, try IPV6 */ + if((r=nr_ice_component_get_default_candidate(comp, candp, NR_IPV4)) && + (r=nr_ice_component_get_default_candidate(comp, candp, NR_IPV6))) { + ABORT(r); } - /* No candidates */ - if (!best_cand) - ABORT(R_NOT_FOUND); - - *candp = best_cand; - _status=0; abort: return(_status); diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_parser.c b/media/mtransport/third_party/nICEr/src/ice/ice_parser.c index ba022e9f932..d52269624bd 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_parser.c +++ b/media/mtransport/third_party/nICEr/src/ice/ice_parser.c @@ -120,7 +120,6 @@ nr_ice_peer_candidate_from_attribute(nr_ice_ctx *ctx,char *orig,nr_ice_media_str nr_ice_candidate *cand; char *connection_address=0; unsigned int port; - in_addr_t addr; int i; unsigned int component_id; char *rel_addr=0; @@ -212,10 +211,6 @@ nr_ice_peer_candidate_from_attribute(nr_ice_ctx *ctx,char *orig,nr_ice_media_str if (*str == '\0') ABORT(R_BAD_DATA); - addr = inet_addr(connection_address); - if (addr == INADDR_NONE) - ABORT(R_BAD_DATA); - skip_whitespace(&str); if (*str == '\0') ABORT(R_BAD_DATA); @@ -226,8 +221,7 @@ nr_ice_peer_candidate_from_attribute(nr_ice_ctx *ctx,char *orig,nr_ice_media_str if (port < 1 || port > 0x0FFFF) ABORT(R_BAD_DATA); - /* Assume v4 for now */ - if(r=nr_ip4_port_to_transport_addr(ntohl(addr),port,transport,&cand->addr)) + if ((r=nr_str_port_to_transport_addr(connection_address,port,transport,&cand->addr))) ABORT(r); skip_to_past_space(&str); @@ -289,10 +283,6 @@ nr_ice_peer_candidate_from_attribute(nr_ice_ctx *ctx,char *orig,nr_ice_media_str if (*str == '\0') ABORT(R_BAD_DATA); - addr = inet_addr(rel_addr); - if (addr == INADDR_NONE) - ABORT(R_BAD_DATA); - skip_whitespace(&str); if (*str == '\0') ABORT(R_BAD_DATA); @@ -314,8 +304,7 @@ nr_ice_peer_candidate_from_attribute(nr_ice_ctx *ctx,char *orig,nr_ice_media_str if (port < 1 || port > 0x0FFFF) ABORT(R_BAD_DATA); - /* Assume v4 for now */ - if(r=nr_ip4_port_to_transport_addr(ntohl(addr),port,transport,&cand->base)) + if ((r=nr_str_port_to_transport_addr(rel_addr,port,transport,&cand->base))) ABORT(r); skip_to_past_space(&str); diff --git a/media/mtransport/third_party/nICEr/src/net/nr_proxy_tunnel.c b/media/mtransport/third_party/nICEr/src/net/nr_proxy_tunnel.c index 6ec0bc0e0b3..c171fb54747 100644 --- a/media/mtransport/third_party/nICEr/src/net/nr_proxy_tunnel.c +++ b/media/mtransport/third_party/nICEr/src/net/nr_proxy_tunnel.c @@ -256,7 +256,7 @@ int nr_socket_proxy_tunnel_connect(void *obj, nr_transport_addr *addr) assert(config->proxy_host); /* Check if the proxy_host is already an IP address */ - has_addr = !nr_ip4_str_port_to_transport_addr(config->proxy_host, + has_addr = !nr_str_port_to_transport_addr(config->proxy_host, config->proxy_port, IPPROTO_TCP, &proxy_addr); r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_connect: %s", config->proxy_host); diff --git a/media/mtransport/third_party/nICEr/src/net/nr_resolver.h b/media/mtransport/third_party/nICEr/src/net/nr_resolver.h index d53388feb03..602454c53d9 100644 --- a/media/mtransport/third_party/nICEr/src/net/nr_resolver.h +++ b/media/mtransport/third_party/nICEr/src/net/nr_resolver.h @@ -46,6 +46,7 @@ typedef struct nr_resolver_resource_ { UINT2 port; int stun_turn; UCHAR transport_protocol; + UCHAR address_family; } nr_resolver_resource; typedef struct nr_resolver_vtbl_ { diff --git a/media/mtransport/third_party/nICEr/src/net/transport_addr.c b/media/mtransport/third_party/nICEr/src/net/transport_addr.c index 2e37cb7a2c6..2ceeabf2de3 100644 --- a/media/mtransport/third_party/nICEr/src/net/transport_addr.c +++ b/media/mtransport/third_party/nICEr/src/net/transport_addr.c @@ -100,44 +100,51 @@ int nr_transport_addr_fmt_ifname_addr_string(const nr_transport_addr *addr, char if (!inet_ntop(AF_INET, &addr->u.addr4.sin_addr,buffer,sizeof(buffer))) { strncpy(buffer, "[error]", len); } - snprintf(buf,len,"%s:%s",addr->ifname,buffer); + break; + case NR_IPV6: + if (!inet_ntop(AF_INET6, &addr->u.addr6.sin6_addr,buffer,sizeof(buffer))) { + strncpy(buffer, "[error]", len); + } break; default: ABORT(R_INTERNAL); } + snprintf(buf,len,"%s:%s",addr->ifname,buffer); _status=0; abort: return(_status); } -int nr_sockaddr_to_transport_addr(struct sockaddr *saddr, int saddr_len, int protocol, int keep, nr_transport_addr *addr) +int nr_sockaddr_to_transport_addr(struct sockaddr *saddr, int protocol, int keep, nr_transport_addr *addr) { int r,_status; if(!keep) memset(addr,0,sizeof(nr_transport_addr)); - if(saddr->sa_family==PF_INET){ - if(saddr_len != sizeof(struct sockaddr_in)) + switch(protocol){ + case IPPROTO_TCP: + case IPPROTO_UDP: + break; + default: ABORT(R_BAD_ARGS); + } - switch(protocol){ - case IPPROTO_TCP: - case IPPROTO_UDP: - break; - default: - ABORT(R_BAD_ARGS); - } + addr->protocol=protocol; + + if(saddr->sa_family==AF_INET){ addr->ip_version=NR_IPV4; - addr->protocol=protocol; memcpy(&addr->u.addr4,saddr,sizeof(struct sockaddr_in)); addr->addr=(struct sockaddr *)&addr->u.addr4; - addr->addr_len=saddr_len; + addr->addr_len=sizeof(struct sockaddr_in); } - else if(saddr->sa_family==PF_INET6){ - /* Not implemented */ - ABORT(R_INTERNAL); + else if(saddr->sa_family==AF_INET6){ + addr->ip_version=NR_IPV6; + + memcpy(&addr->u.addr6, saddr, sizeof(struct sockaddr_in6)); + addr->addr=(struct sockaddr *)&addr->u.addr6; + addr->addr_len=sizeof(struct sockaddr_in6); } else ABORT(R_BAD_ARGS); @@ -206,16 +213,42 @@ int nr_ip4_port_to_transport_addr(UINT4 ip4, UINT2 port, int protocol, nr_transp return(_status); } -int nr_ip4_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 *ip, UINT2 port, int protocol, nr_transport_addr *addr_out) { int r,_status; - in_addr_t ip_addr; + struct in_addr addr; + struct in6_addr addr6; - ip_addr=inet_addr(ip4); - if (ip_addr == INADDR_NONE) + if (inet_pton(AF_INET, ip, &addr) == 1) { + if(r=nr_ip4_port_to_transport_addr(ntohl(addr.s_addr),port,protocol,addr_out)) + ABORT(r); + } else if (inet_pton(AF_INET6, ip, &addr6) == 1) { + if(r=nr_ip6_port_to_transport_addr(&addr6,port,protocol,addr_out)) + ABORT(r); + } else { ABORT(R_BAD_DATA); - /* Assume v4 for now */ - if(r=nr_ip4_port_to_transport_addr(ntohl(ip_addr),port,protocol,addr)) + } + + _status=0; + abort: + return(_status); + } + +int nr_ip6_port_to_transport_addr(struct in6_addr* addr6, UINT2 port, int protocol, nr_transport_addr *addr) + { + int r,_status; + + memset(addr, 0, sizeof(nr_transport_addr)); + + addr->ip_version=NR_IPV6; + addr->protocol=protocol; + addr->u.addr6.sin6_family=PF_INET6; + addr->u.addr6.sin6_port=htons(port); + memcpy(addr->u.addr6.sin6_addr.s6_addr, addr6->s6_addr, sizeof(addr6->s6_addr)); + addr->addr=(struct sockaddr *)&addr->u.addr6; + addr->addr_len=sizeof(struct sockaddr_in6); + + if(r=nr_transport_addr_fmt_addr_string(addr)) ABORT(r); _status=0; @@ -291,26 +324,6 @@ int nr_transport_addr_set_port(nr_transport_addr *addr, int port) return(_status); } -int nr_transport_addr_get_ip4(nr_transport_addr *addr, UINT4 *ip4p) - { - int _status; - - switch(addr->ip_version){ - case NR_IPV4: - *ip4p=ntohl(addr->u.addr4.sin_addr.s_addr); - break; - case NR_IPV6: - ABORT(R_NOT_FOUND); - break; - default: - ABORT(R_INTERNAL); - } - - _status=0; - abort: - return(_status); - } - /* memcmp() may not work if, for instance, the string or interface haven't been made. Hmmm.. */ int nr_transport_addr_cmp(nr_transport_addr *addr1,nr_transport_addr *addr2,int mode) @@ -340,7 +353,13 @@ int nr_transport_addr_cmp(nr_transport_addr *addr1,nr_transport_addr *addr2,int return(1); break; case NR_IPV6: - UNIMPLEMENTED; + if(memcmp(addr1->u.addr6.sin6_addr.s6_addr,addr2->u.addr6.sin6_addr.s6_addr,sizeof(struct in6_addr))) + return(1); + if(mode < NR_TRANSPORT_ADDR_CMP_MODE_ALL) + return(0); + if(addr1->u.addr6.sin6_port != addr2->u.addr6.sin6_port) + return(1); + break; default: abort(); } @@ -363,6 +382,10 @@ int nr_transport_addr_is_loopback(nr_transport_addr *addr) } break; + case NR_IPV6: + if(!memcmp(addr->u.addr6.sin6_addr.s6_addr,in6addr_loopback.s6_addr,sizeof(struct in6_addr))) + return(1); + break; default: UNIMPLEMENTED; } @@ -370,6 +393,18 @@ int nr_transport_addr_is_loopback(nr_transport_addr *addr) return(0); } +int nr_transport_addr_is_link_local(nr_transport_addr *addr) + { + if(addr->ip_version == NR_IPV6){ + UINT4* addrTop = (UINT4*)(addr->u.addr6.sin6_addr.s6_addr); + return ((*addrTop & htonl(0xFFC00000)) == htonl(0xFE800000)); + } else { + assert(0); + } + + return(0); + } + int nr_transport_addr_is_wildcard(nr_transport_addr *addr) { switch(addr->ip_version){ @@ -379,6 +414,12 @@ int nr_transport_addr_is_wildcard(nr_transport_addr *addr) if(addr->u.addr4.sin_port==0) return(1); break; + case NR_IPV6: + if(!memcmp(addr->u.addr6.sin6_addr.s6_addr,in6addr_any.s6_addr,sizeof(struct in6_addr))) + return(1); + if(addr->u.addr6.sin6_port==0) + return(1); + break; default: UNIMPLEMENTED; } diff --git a/media/mtransport/third_party/nICEr/src/net/transport_addr.h b/media/mtransport/third_party/nICEr/src/net/transport_addr.h index 6ae014b80b9..dccc4b16b0b 100644 --- a/media/mtransport/third_party/nICEr/src/net/transport_addr.h +++ b/media/mtransport/third_party/nICEr/src/net/transport_addr.h @@ -71,15 +71,15 @@ typedef struct nr_transport_addr_ { char as_string[56]; } nr_transport_addr; -int nr_sockaddr_to_transport_addr(struct sockaddr *saddr, int saddr_len, int protocol, int keep, nr_transport_addr *addr); +int nr_sockaddr_to_transport_addr(struct sockaddr *saddr, int protocol, int keep, nr_transport_addr *addr); // 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_ip4_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 *ip4, 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); int nr_transport_addr_get_port(nr_transport_addr *addr, int *port); -int nr_transport_addr_get_ip4(nr_transport_addr *addr, UINT4 *ip4p); int nr_transport_addr_cmp(nr_transport_addr *addr1,nr_transport_addr *addr2,int mode); #define NR_TRANSPORT_ADDR_CMP_MODE_VERSION 1 #define NR_TRANSPORT_ADDR_CMP_MODE_PROTOCOL 2 @@ -88,6 +88,7 @@ int nr_transport_addr_cmp(nr_transport_addr *addr1,nr_transport_addr *addr2,int int nr_transport_addr_is_wildcard(nr_transport_addr *addr); int nr_transport_addr_is_loopback(nr_transport_addr *addr); +int nr_transport_addr_is_link_local(nr_transport_addr *addr); int nr_transport_addr_copy(nr_transport_addr *to, nr_transport_addr *from); int nr_transport_addr_copy_keep_ifname(nr_transport_addr *to, nr_transport_addr *from); int nr_transport_addr_fmt_addr_string(nr_transport_addr *addr); diff --git a/media/mtransport/third_party/nICEr/src/net/transport_addr_reg.c b/media/mtransport/third_party/nICEr/src/net/transport_addr_reg.c index 7d5d59bc6b6..eca70c16376 100644 --- a/media/mtransport/third_party/nICEr/src/net/transport_addr_reg.c +++ b/media/mtransport/third_party/nICEr/src/net/transport_addr_reg.c @@ -53,6 +53,9 @@ static char *RCSSTRING __UNUSED__="$Id: transport_addr_reg.c,v 1.2 2008/04/28 17 #include "transport_addr.h" #include "transport_addr_reg.h" +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 46 /* Value used by linux/BSD */ +#endif int nr_reg_get_transport_addr(NR_registry prefix, int keep, nr_transport_addr *addr) @@ -107,7 +110,7 @@ nr_reg_get_transport_addr(NR_registry prefix, int keep, nr_transport_addr *addr) if (!keep) memset(addr, 0, sizeof(*addr)); - if ((r=nr_ip4_str_port_to_transport_addr(address?address:"0.0.0.0", port, p, addr))) + if ((r=nr_str_port_to_transport_addr(address?address:"0.0.0.0", port, p, addr))) ABORT(r); if (ifname) @@ -133,7 +136,7 @@ nr_reg_set_transport_addr(NR_registry prefix, int keep, nr_transport_addr *addr) switch (addr->ip_version) { case NR_IPV4: - if (addr->u.addr4.sin_addr.s_addr != INADDR_ANY) { + if (!nr_transport_addr_is_wildcard(addr)) { if ((r=NR_reg_set2_string(prefix, "address", inet_ntoa(addr->u.addr4.sin_addr)))) ABORT(r); } @@ -142,35 +145,50 @@ nr_reg_set_transport_addr(NR_registry prefix, int keep, nr_transport_addr *addr) if ((r=NR_reg_set2_uint2(prefix, "port", ntohs(addr->u.addr4.sin_port)))) ABORT(r); } - - switch (addr->protocol) { - case IPPROTO_TCP: - if ((r=NR_reg_set2_string(prefix, "protocol", "tcp"))) - ABORT(r); - break; - case IPPROTO_UDP: - if ((r=NR_reg_set2_string(prefix, "protocol", "udp"))) - ABORT(r); - break; - default: - UNIMPLEMENTED; - break; - } - - if (strlen(addr->ifname) > 0) { - if ((r=NR_reg_set2_string(prefix, "ifname", addr->ifname))) - ABORT(r); - } break; case NR_IPV6: - UNIMPLEMENTED; + if (!nr_transport_addr_is_wildcard(addr)) { + char address[INET6_ADDRSTRLEN]; + if(!inet_ntop(AF_INET6, &addr->u.addr6.sin6_addr,address,sizeof(address))) { + ABORT(R_BAD_DATA); + } + + if ((r=NR_reg_set2_string(prefix, "address", address))) { + ABORT(r); + } + } + + if (addr->u.addr6.sin6_port != 0) { + if ((r=NR_reg_set2_uint2(prefix, "port", ntohs(addr->u.addr6.sin6_port)))) + ABORT(r); + } break; default: ABORT(R_INTERNAL); break; } + /* We abort if neither NR_IPV4 or NR_IPV6 above */ + switch (addr->protocol) { + case IPPROTO_TCP: + if ((r=NR_reg_set2_string(prefix, "protocol", "tcp"))) + ABORT(r); + break; + case IPPROTO_UDP: + if ((r=NR_reg_set2_string(prefix, "protocol", "udp"))) + ABORT(r); + break; + default: + UNIMPLEMENTED; + break; + } + + if (strlen(addr->ifname) > 0) { + if ((r=NR_reg_set2_string(prefix, "ifname", addr->ifname))) + ABORT(r); + } + _status=0; abort: if (_status) diff --git a/media/mtransport/third_party/nICEr/src/stun/addrs.c b/media/mtransport/third_party/nICEr/src/stun/addrs.c index 4ce7037e48c..c007a5a8da1 100644 --- a/media/mtransport/third_party/nICEr/src/stun/addrs.c +++ b/media/mtransport/third_party/nICEr/src/stun/addrs.c @@ -41,267 +41,42 @@ static char *RCSSTRING __UNUSED__="$Id: addrs.c,v 1.2 2008/04/28 18:21:30 ekr Ex #include #include #include -#else /* UNIX */ -#include +#else /* !WIN32 */ + #include +#include +#include + #ifndef ANDROID -#include +/* This works on linux and BSD, but not android */ +#include /* getifaddrs */ +#include /* getifaddrs */ #else -#include +#include "ifaddrs-android.h" +#define getifaddrs android_getifaddrs +#define freeifaddrs android_freeifaddrs +#endif + +#ifdef LINUX + +#ifdef ANDROID /* Work around an Android NDK < r8c bug */ #undef __unused -#endif -#ifndef LINUX -#include -#if !defined(__OpenBSD__) && !defined(__NetBSD__) -#include -#endif -#include -#include -#include #else -#include -#include -#include -#include -#ifndef ANDROID -#include -#endif -#endif -#include +#include /* struct ifreq, IFF_POINTTOPOINT */ +#include /* struct iwreq */ +#include /* struct ethtool_cmd */ +#include /* SIOCETHTOOL */ +#endif /* ANDROID */ -/* IP */ -#include -#ifdef LINUX -#include "sys/ioctl.h" -#else -#include -#endif -#include -#include -#endif /* UNIX */ +#endif /* LINUX */ + +#endif /* !WIN32 */ #include "stun.h" #include "addrs.h" - - -#if defined(BSD) || defined(DARWIN) -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - *[3 Deleted as of 22nd July 1999; see - * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change - * for details] - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include - -static void stun_rt_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *); -static int stun_grab_addrs(char *name, int addrcount, - struct ifa_msghdr *ifam, - nr_local_addr addrs[], int maxaddrs, int *count); -static int -nr_stun_is_duplicate_addr(nr_local_addr addrs[], int count, nr_local_addr *addr); - - -/* - * Expand the compacted form of addresses as returned via the - * configuration read via sysctl(). - */ -#define ROUNDUP(a) \ - ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) -#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) - -static void -stun_rt_xaddrs(cp, cplim, rtinfo) - caddr_t cp, cplim; - struct rt_addrinfo *rtinfo; -{ - struct sockaddr *sa; - int i; - - memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info)); - for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { - if ((rtinfo->rti_addrs & (1 << i)) == 0) - continue; - rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; - ADVANCE(cp, sa); - } -} - -static int -stun_grab_addrs(char *name, int addrcount, struct ifa_msghdr *ifam, nr_local_addr addrs[], int maxaddrs, int *count) -{ - int r,_status; - int s = -1; - struct ifreq ifr; - struct rt_addrinfo info; - struct sockaddr_in *sin; - - ifr.ifr_addr.sa_family = AF_INET; - strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); - - if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) { - r_log(NR_LOG_STUN, LOG_ERR, "unable to obtain addresses from socket"); - ABORT(R_FAILED); - } - - while (addrcount > 0) { - info.rti_addrs = ifam->ifam_addrs; - - /* Expand the compacted addresses */ - stun_rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, &info); - addrs[*count].interface.type = NR_INTERFACE_TYPE_UNKNOWN; - addrs[*count].interface.estimated_speed = 0; - /* TODO (Bug 895790) Get interface properties for Darwin */ - - switch (info.rti_info[RTAX_IFA]->sa_family) { - case AF_INET: - sin = (struct sockaddr_in *)info.rti_info[RTAX_IFA]; - - if ((r=nr_sockaddr_to_transport_addr((struct sockaddr*)sin, sizeof(*sin), IPPROTO_UDP, 0, &(addrs[*count].addr)))) - ABORT(r); - - strlcpy(addrs[*count].addr.ifname, name, sizeof(addrs[*count].addr.ifname)); - - ++*count; - break; - case AF_INET6: - UNIMPLEMENTED; - break; - } - - addrcount--; - - if (*count >= maxaddrs) { - r_log(NR_LOG_STUN, LOG_WARNING, "Address list truncated at %d out of %d entries", maxaddrs, maxaddrs+addrcount); - break; - } - - ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen); - } - - _status = 0; - abort: - if (s != -1) close(s); - return _status; -} - -static int -stun_get_mib_addrs(nr_local_addr addrs[], int maxaddrs, int *count) -{ - int _status; - char name[32]; - int flags; - int addrcount; - struct if_msghdr *ifm, *nextifm; - struct ifa_msghdr *ifam; - struct sockaddr_dl *sdl; - char *buf = 0; - char *lim; - char *next; - size_t needed; - int mib[6]; - - *count = 0; - - mib[0] = CTL_NET; - mib[1] = PF_ROUTE; - mib[2] = 0; - mib[3] = AF_INET; - mib[4] = NET_RT_IFLIST; - mib[5] = 0; - - if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { - errx(1, "iflist-sysctl-estimate"); - ABORT(R_INTERNAL); - } - - if ((buf = malloc(needed)) == NULL) { - errx(1, "malloc"); - ABORT(R_NO_MEMORY); - } - - if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { - errx(1, "actual retrieval of interface table"); - ABORT(R_INTERNAL); - } - - lim = buf + needed; - - next = buf; - while (next < lim) { - ifm = (struct if_msghdr *)next; - - if (ifm->ifm_type == RTM_IFINFO) { - sdl = (struct sockaddr_dl *)(ifm + 1); - flags = ifm->ifm_flags; - } else { - r_log(NR_LOG_STUN, LOG_WARNING, "out of sync parsing NET_RT_IFLIST"); - r_log(NR_LOG_STUN, LOG_DEBUG, "expected %d, got %d, msglen = %d, buf:%p, next:%p, lim:%p", RTM_IFINFO, ifm->ifm_type, ifm->ifm_msglen, buf, next, lim); - ABORT(R_FAILED); - } - - next += ifm->ifm_msglen; - ifam = NULL; - addrcount = 0; - while (next < lim) { - - nextifm = (struct if_msghdr *)next; - - if (nextifm->ifm_type != RTM_NEWADDR) - break; - - if (ifam == NULL) - ifam = (struct ifa_msghdr *)nextifm; - - addrcount++; - next += nextifm->ifm_msglen; - } - - if (sdl->sdl_nlen > sizeof(name) - 1) { - ABORT(R_INTERNAL); - } - - memcpy(name, sdl->sdl_data, sdl->sdl_nlen); - name[sdl->sdl_nlen] = '\0'; - - stun_grab_addrs(name, addrcount, ifam, addrs, maxaddrs, count); - } - - _status = 0; -abort: - if (buf) free(buf); - return _status; -} - -#elif defined(WIN32) +#if defined(WIN32) #define WIN32_MAX_NUM_INTERFACES 20 @@ -368,125 +143,6 @@ abort: return(_status); } - -static int -stun_get_win32_addrs(nr_local_addr addrs[], int maxaddrs, int *count) -{ - int r,_status; - PIP_ADAPTER_INFO pAdapterInfo; - PIP_ADAPTER_INFO pAdapter = NULL; - PIP_ADDR_STRING pAddrString; - ULONG out_buf_len; - char *friendly_name=0; - char munged_ifname[IFNAMSIZ]; - int n = 0; - - *count = 0; - - pAdapterInfo = (IP_ADAPTER_INFO *) RMALLOC(sizeof(IP_ADAPTER_INFO)); - out_buf_len = sizeof(IP_ADAPTER_INFO); - - /* First call to GetAdaptersInfo is mainly to get length */ - - if (GetAdaptersInfo(pAdapterInfo, &out_buf_len) == ERROR_BUFFER_OVERFLOW) { - RFREE(pAdapterInfo); - pAdapterInfo = (IP_ADAPTER_INFO *) RMALLOC(out_buf_len); - if (pAdapterInfo == NULL) { - r_log(NR_LOG_STUN, LOG_ERR, "Error allocating memory for GetAdaptersInfo output"); - ABORT(R_NO_MEMORY); - } - } - if ((r = GetAdaptersInfo(pAdapterInfo, &out_buf_len)) != NO_ERROR) { - r_log(NR_LOG_STUN, LOG_ERR, "Got error from GetAdaptersInfo"); - ABORT(R_INTERNAL); - } - r_log(NR_LOG_STUN, LOG_DEBUG, "Got AdaptersInfo"); - - pAdapter = pAdapterInfo; - - while (pAdapter) { - char *c; - - r_log(NR_LOG_STUN, LOG_DEBUG, "Adapter Name (GUID) = %s", pAdapter->AdapterName); - r_log(NR_LOG_STUN, LOG_DEBUG, "Adapter Description = %s", pAdapter->Description); - - if (nr_win32_get_adapter_friendly_name(pAdapter->AdapterName, &friendly_name)) { - friendly_name = 0; - } - if (friendly_name && *friendly_name) { - r_log(NR_LOG_STUN, LOG_INFO, "Found adapter with friendly name: %s", friendly_name); - snprintf(munged_ifname, IFNAMSIZ, "%s%c", friendly_name, 0); - RFREE(friendly_name); - friendly_name = 0; - } else { - // Not all adapters follow the friendly name convention. Windows' PPTP - // VPN adapter puts "VPN Connection 2" in the Description field instead. - // Windows's renaming-logic appears to enforce uniqueness in spite of this. - r_log(NR_LOG_STUN, LOG_INFO, "Found adapter with description: %s", pAdapter->Description); - snprintf(munged_ifname, IFNAMSIZ, "%s%c", pAdapter->Description, 0); - } - /* replace spaces with underscores */ - c = strchr(munged_ifname, ' '); - while (c != NULL) { - *c = '_'; - c = strchr(munged_ifname, ' '); - } - c = strchr(munged_ifname, '.'); - while (c != NULL) { - *c = '+'; - c = strchr(munged_ifname, '.'); - } - - r_log(NR_LOG_STUN, LOG_INFO, "Converted ifname: %s", munged_ifname); - - for (pAddrString = &(pAdapter->IpAddressList); pAddrString != NULL; pAddrString = pAddrString->Next) { - unsigned long this_addr = inet_addr(pAddrString->IpAddress.String); - nr_transport_addr *addr = &(addrs[n].addr); - - if (this_addr == 0) - continue; - - r_log(NR_LOG_STUN, LOG_INFO, "Adapter %s address: %s", munged_ifname, pAddrString->IpAddress.String); - - addr->ip_version=NR_IPV4; - addr->protocol = IPPROTO_UDP; - - addr->u.addr4.sin_family=PF_INET; - addr->u.addr4.sin_port=0; - addr->u.addr4.sin_addr.s_addr=this_addr; - addr->addr=(struct sockaddr *)&(addr->u.addr4); - addr->addr_len=sizeof(struct sockaddr_in); - - strlcpy(addr->ifname, munged_ifname, sizeof(addr->ifname)); - snprintf(addr->as_string,40,"IP4:%s:%d", - inet_ntoa(addr->u.addr4.sin_addr), - ntohs(addr->u.addr4.sin_port)); - - /* TODO: (Bug 895793) Getting interface properties for Windows */ - addrs[n].interface.type = NR_INTERFACE_TYPE_UNKNOWN; - addrs[n].interface.estimated_speed = 0; - - if (++n >= maxaddrs) - goto done; - } - - pAdapter = pAdapter->Next; - } - - done: - *count = n; - _status = 0; - - abort: - RFREE(pAdapterInfo); - RFREE(friendly_name); - return _status; -} - -#ifdef GET_WIN32_ADDRS_NO_WIN2K - /* Here's a nice way to get adapter addresses and names, but it - * isn't supported on Win2000. - */ static int stun_get_win32_addrs(nr_local_addr addrs[], int maxaddrs, int *count) { @@ -505,7 +161,7 @@ stun_get_win32_addrs(nr_local_addr addrs[], int maxaddrs, int *count) buflen = 0; - r = GetAdaptersAddresses(AF_INET, 0, NULL, AdapterAddresses, &buflen); + r = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, AdapterAddresses, &buflen); if (r != ERROR_BUFFER_OVERFLOW) { r_log(NR_LOG_STUN, LOG_ERR, "Error getting buf len from GetAdaptersAddresses()"); ABORT(R_INTERNAL); @@ -519,7 +175,7 @@ stun_get_win32_addrs(nr_local_addr addrs[], int maxaddrs, int *count) /* for real, this time */ - r = GetAdaptersAddresses(AF_INET, 0, NULL, AdapterAddresses, &buflen); + r = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, AdapterAddresses, &buflen); if (r != NO_ERROR) { r_log(NR_LOG_STUN, LOG_ERR, "Error getting addresses from GetAdaptersAddresses()"); ABORT(R_INTERNAL); @@ -554,7 +210,7 @@ stun_get_win32_addrs(nr_local_addr addrs[], int maxaddrs, int *count) if ((sa_addr->lpSockaddr->sa_family == AF_INET) || (sa_addr->lpSockaddr->sa_family == AF_INET6)) { - if ((r=nr_sockaddr_to_transport_addr((struct sockaddr*)sa_addr->lpSockaddr, sizeof(*sa_addr->lpSockaddr), IPPROTO_UDP, 0, &(addrs[n].addr)))) + if ((r=nr_sockaddr_to_transport_addr((struct sockaddr*)sa_addr->lpSockaddr, IPPROTO_UDP, 0, &(addrs[n].addr)))) ABORT(r); } else { @@ -580,131 +236,98 @@ stun_get_win32_addrs(nr_local_addr addrs[], int maxaddrs, int *count) RFREE(AdapterAddresses); return _status; } -#endif /* GET_WIN32_ADDRS_NO_WIN2K */ -#elif defined(__sparc__) +#else /* WIN32 */ static int -stun_get_sparc_addrs(nr_local_addr addrs[], int maxaddrs, int *count) -{ - *count = 0; - UNIMPLEMENTED; /*TODO !nn! - sparc */ - return 0; -} - -#else +nr_stun_is_duplicate_addr(nr_local_addr addrs[], int count, nr_local_addr *addr); static int -stun_get_siocgifconf_addrs(nr_local_addr addrs[], int maxaddrs, int *count) +stun_getifaddrs(nr_local_addr addrs[], int maxaddrs, int *count) { - struct ifconf ifc; - int _status; - int s = socket( AF_INET, SOCK_DGRAM, 0 ); - int len = 100 * sizeof(struct ifreq); - int r; - int e; - char *ptr; - int tl; - int n; - struct ifreq ifr2; + int r,_status; + struct ifaddrs* if_addrs_head=NULL; + struct ifaddrs* if_addr; - char buf[ len ]; + *count=0; - ifc.ifc_len = len; - ifc.ifc_buf = buf; + if (getifaddrs(&if_addrs_head) == -1) { + r_log(NR_LOG_STUN, LOG_ERR, "getifaddrs error e = %d", errno); + ABORT(R_INTERNAL); + } - e = ioctl(s,SIOCGIFCONF,&ifc); + if_addr = if_addrs_head; - if ( e == -1 ) - { - return(R_INTERNAL); - } - - ptr = buf; - tl = ifc.ifc_len; - n=0; - - while ( (tl > 0) && ( n < maxaddrs) ) - { - struct ifreq* ifr = (struct ifreq *)ptr; - -#ifdef LINUX - int si = sizeof(struct ifreq); -#ifndef ANDROID - struct ethtool_cmd ecmd; - struct iwreq wrq; -#endif -#else - int si = sizeof(ifr->ifr_name) + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr)); -#endif - tl -= si; - ptr += si; - - ifr2 = *ifr; - - e = ioctl(s,SIOCGIFADDR,&ifr2); - if ( e == -1 ) - { - continue; - } - - //r_log(NR_LOG_STUN, LOG_ERR, "ioctl addr e = %d",e); - - if ((r=nr_sockaddr_to_transport_addr(&ifr2.ifr_addr, sizeof(ifr2.ifr_addr), IPPROTO_UDP, 0, &(addrs[n].addr)))) { - r_log(NR_LOG_STUN, LOG_WARNING, "Problem transforming address"); - } - else { - addrs[n].interface.type = NR_INTERFACE_TYPE_UNKNOWN; - addrs[n].interface.estimated_speed = 0; + while (if_addr && *count < maxaddrs) { + switch (if_addr->ifa_addr->sa_family) { + case AF_INET: + case AF_INET6: + if (r=nr_sockaddr_to_transport_addr(if_addr->ifa_addr, IPPROTO_UDP, 0, &(addrs[*count].addr))) { + r_log(NR_LOG_STUN, LOG_ERR, "nr_sockaddr_to_transport_addr error r = %d", r); + } else { #if defined(LINUX) && !defined(ANDROID) + struct ethtool_cmd ecmd; + struct ifreq ifr; + struct iwreq wrq; + int e; + int s = socket(AF_INET, SOCK_DGRAM, 0); + + strncpy(ifr.ifr_name, if_addr->ifa_name, sizeof(ifr.ifr_name)); /* TODO (Bug 896851): interface property for Android */ /* Getting ethtool for ethernet information. */ ecmd.cmd = ETHTOOL_GSET; - ifr2.ifr_data = (void*)&ecmd; - e = ioctl(s, SIOCETHTOOL, &ifr2); + /* In/out param */ + ifr.ifr_data = (void*)&ecmd; + + e = ioctl(s, SIOCETHTOOL, &ifr); if (e == 0) { /* For wireless network, we won't get ethtool, it's a wired - connection */ - addrs[n].interface.type = NR_INTERFACE_TYPE_WIRED; + * connection */ + addrs[*count].interface.type = NR_INTERFACE_TYPE_WIRED; #ifdef DONT_HAVE_ETHTOOL_SPEED_HI - addrs[n].interface.estimated_speed = ecmd.speed; + addrs[*count].interface.estimated_speed = ecmd.speed; #else - addrs[n].interface.estimated_speed = ((ecmd.speed_hi << 16) | ecmd.speed) * 1000; + addrs[*count].interface.estimated_speed = ((ecmd.speed_hi << 16) | ecmd.speed) * 1000; #endif } - strncpy(wrq.ifr_name, ifr->ifr_name, sizeof(wrq.ifr_name)); + strncpy(wrq.ifr_name, if_addr->ifa_name, sizeof(wrq.ifr_name)); e = ioctl(s, SIOCGIWRATE, &wrq); if (e == 0) { - addrs[n].interface.type = NR_INTERFACE_TYPE_WIFI; - addrs[n].interface.estimated_speed = wrq.u.bitrate.value / 1000; + addrs[*count].interface.type = NR_INTERFACE_TYPE_WIFI; + addrs[*count].interface.estimated_speed = wrq.u.bitrate.value / 1000; } - ifr2 = *ifr; - e = ioctl(s, SIOCGIFFLAGS, &ifr2); - if (e == 0) + if (if_addr->ifa_flags & IFF_POINTOPOINT) { - if (ifr2.ifr_flags & IFF_POINTOPOINT) - { - addrs[n].interface.type = NR_INTERFACE_TYPE_UNKNOWN | NR_INTERFACE_TYPE_VPN; - /* TODO (Bug 896913): find backend network type of this VPN */ - } + addrs[*count].interface.type = NR_INTERFACE_TYPE_UNKNOWN | NR_INTERFACE_TYPE_VPN; + /* TODO (Bug 896913): find backend network type of this VPN */ } +#else + addrs[*count].interface.type = NR_INTERFACE_TYPE_UNKNOWN; + addrs[*count].interface.estimated_speed = 0; #endif - strlcpy(addrs[n].addr.ifname, ifr->ifr_name, sizeof(addrs[n].addr.ifname)); - ++n; - } - } + strlcpy(addrs[*count].addr.ifname, if_addr->ifa_name, sizeof(addrs[*count].addr.ifname)); + ++(*count); + } + break; + default: + ; + } - close(s); + if_addr = if_addr->ifa_next; + } - *count = n; - - _status = 0; - return _status; + _status=0; +abort: + if (if_addrs_head) { + freeifaddrs(if_addrs_head); + } + return(_status); } + #endif static int @@ -724,7 +347,7 @@ nr_stun_is_duplicate_addr(nr_local_addr addrs[], int count, nr_local_addr *addr) } int -nr_stun_remove_duplicate_addrs(nr_local_addr addrs[], int remove_loopback, int *count) +nr_stun_remove_duplicate_addrs(nr_local_addr addrs[], int remove_loopback, int remove_link_local, int *count) { int r, _status; nr_local_addr *tmp = 0; @@ -743,6 +366,11 @@ nr_stun_remove_duplicate_addrs(nr_local_addr addrs[], int remove_loopback, int * else if (remove_loopback && nr_transport_addr_is_loopback(&addrs[i].addr)) { /* skip addrs[i], it's a loopback */ } + else if (remove_link_local && + addrs[i].addr.ip_version == NR_IPV6 && + nr_transport_addr_is_link_local(&addrs[i].addr)) { + /* skip addrs[i], it's a link-local address */ + } else { /* otherwise, copy it to the temporary array */ if ((r=nr_local_addr_copy(&tmp[n], &addrs[i]))) @@ -768,23 +396,19 @@ nr_stun_remove_duplicate_addrs(nr_local_addr addrs[], int remove_loopback, int * #ifndef USE_PLATFORM_NR_STUN_GET_ADDRS int -nr_stun_get_addrs(nr_local_addr addrs[], int maxaddrs, int drop_loopback, int *count) +nr_stun_get_addrs(nr_local_addr addrs[], int maxaddrs, int drop_loopback, int drop_link_local, int *count) { int _status=0; int i; char typestr[100]; -#if defined(BSD) || defined(DARWIN) - _status = stun_get_mib_addrs(addrs, maxaddrs, count); -#elif defined(WIN32) +#ifdef WIN32 _status = stun_get_win32_addrs(addrs, maxaddrs, count); -#elif defined(__sparc__) - _status = stun_get_sparc_addrs(addrs, maxaddrs, count); #else - _status = stun_get_siocgifconf_addrs(addrs, maxaddrs, count); + _status = stun_getifaddrs(addrs, maxaddrs, count); #endif - nr_stun_remove_duplicate_addrs(addrs, drop_loopback, count); + nr_stun_remove_duplicate_addrs(addrs, drop_loopback, drop_link_local, count); for (i = 0; i < *count; ++i) { nr_local_addr_fmt_info_string(addrs+i,typestr,sizeof(typestr)); diff --git a/media/mtransport/third_party/nICEr/src/stun/addrs.h b/media/mtransport/third_party/nICEr/src/stun/addrs.h index 76abbe08ceb..61a3496d13b 100644 --- a/media/mtransport/third_party/nICEr/src/stun/addrs.h +++ b/media/mtransport/third_party/nICEr/src/stun/addrs.h @@ -37,7 +37,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "transport_addr.h" #include "local_addr.h" -int nr_stun_get_addrs(nr_local_addr addrs[], int maxaddrs, int remove_loopback, int *count); -int nr_stun_remove_duplicate_addrs(nr_local_addr addrs[], int remove_loopback,int *count); +int nr_stun_get_addrs(nr_local_addr addrs[], int maxaddrs, int remove_loopback, int remove_link_local, int *count); +int nr_stun_remove_duplicate_addrs(nr_local_addr addrs[], int remove_loopback, int remove_link_local, int *count); #endif diff --git a/media/mtransport/third_party/nICEr/src/stun/ifaddrs-android.c b/media/mtransport/third_party/nICEr/src/stun/ifaddrs-android.c new file mode 100644 index 00000000000..d7d390f243b --- /dev/null +++ b/media/mtransport/third_party/nICEr/src/stun/ifaddrs-android.c @@ -0,0 +1,242 @@ +/* +Copyright (c) 2011, The WebRTC project authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Google nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#if defined(ANDROID) +#include "ifaddrs-android.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct netlinkrequest { + struct nlmsghdr header; + struct ifaddrmsg msg; +}; + +static const int kMaxReadSize = 4096; + +static int set_ifname(struct ifaddrs* ifaddr, int interface) { + char buf[IFNAMSIZ] = {0}; + char* name = if_indextoname(interface, buf); + if (name == NULL) { + return -1; + } + ifaddr->ifa_name = malloc(strlen(name) + 1); + strncpy(ifaddr->ifa_name, name, strlen(name) + 1); + return 0; +} + +static int set_flags(struct ifaddrs* ifaddr) { + int fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd == -1) { + return -1; + } + struct ifreq ifr; + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, ifaddr->ifa_name, IFNAMSIZ - 1); + int rc = ioctl(fd, SIOCGIFFLAGS, &ifr); + close(fd); + if (rc == -1) { + return -1; + } + ifaddr->ifa_flags = ifr.ifr_flags; + return 0; +} + +static int set_addresses(struct ifaddrs* ifaddr, struct ifaddrmsg* msg, void* data, + size_t len) { + if (msg->ifa_family == AF_INET) { + struct sockaddr_in* sa = malloc(sizeof(struct sockaddr_in)); + memset(sa, 0, sizeof(struct sockaddr_in)); + sa->sin_family = AF_INET; + memcpy(&sa->sin_addr, data, len); + ifaddr->ifa_addr = (struct sockaddr*)sa; + } else if (msg->ifa_family == AF_INET6) { + struct sockaddr_in6* sa = malloc(sizeof(struct sockaddr_in6)); + memset(sa, 0, sizeof(struct sockaddr_in6)); + sa->sin6_family = AF_INET6; + sa->sin6_scope_id = msg->ifa_index; + memcpy(&sa->sin6_addr, data, len); + ifaddr->ifa_addr = (struct sockaddr*)sa; + } else { + return -1; + } + return 0; +} + +static int make_prefixes(struct ifaddrs* ifaddr, int family, int prefixlen) { + char* prefix = NULL; + if (family == AF_INET) { + struct sockaddr_in* mask = malloc(sizeof(struct sockaddr_in)); + memset(mask, 0, sizeof(struct sockaddr_in)); + mask->sin_family = AF_INET; + memset(&mask->sin_addr, 0, sizeof(struct in_addr)); + ifaddr->ifa_netmask = (struct sockaddr*)mask; + if (prefixlen > 32) { + prefixlen = 32; + } + prefix = (char*)&mask->sin_addr; + } else if (family == AF_INET6) { + struct sockaddr_in6* mask = malloc(sizeof(struct sockaddr_in6)); + memset(mask, 0, sizeof(struct sockaddr_in6)); + mask->sin6_family = AF_INET6; + memset(&mask->sin6_addr, 0, sizeof(struct in6_addr)); + ifaddr->ifa_netmask = (struct sockaddr*)mask; + if (prefixlen > 128) { + prefixlen = 128; + } + prefix = (char*)&mask->sin6_addr; + } else { + return -1; + } + for (int i = 0; i < (prefixlen / 8); i++) { + *prefix++ = 0xFF; + } + char remainder = 0xff; + remainder <<= (8 - prefixlen % 8); + *prefix = remainder; + return 0; +} + +static int populate_ifaddrs(struct ifaddrs* ifaddr, struct ifaddrmsg* msg, void* bytes, + size_t len) { + if (set_ifname(ifaddr, msg->ifa_index) != 0) { + return -1; + } + if (set_flags(ifaddr) != 0) { + return -1; + } + if (set_addresses(ifaddr, msg, bytes, len) != 0) { + return -1; + } + if (make_prefixes(ifaddr, msg->ifa_family, msg->ifa_prefixlen) != 0) { + return -1; + } + return 0; +} + +int android_getifaddrs(struct ifaddrs** result) { + int fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (fd < 0) { + return -1; + } + + struct netlinkrequest ifaddr_request; + memset(&ifaddr_request, 0, sizeof(ifaddr_request)); + ifaddr_request.header.nlmsg_flags = NLM_F_ROOT | NLM_F_REQUEST; + ifaddr_request.header.nlmsg_type = RTM_GETADDR; + ifaddr_request.header.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); + + ssize_t count = send(fd, &ifaddr_request, ifaddr_request.header.nlmsg_len, 0); + if ((size_t)count != ifaddr_request.header.nlmsg_len) { + close(fd); + return -1; + } + struct ifaddrs* start = NULL; + struct ifaddrs* current = NULL; + char buf[kMaxReadSize]; + ssize_t amount_read = recv(fd, &buf, kMaxReadSize, 0); + while (amount_read > 0) { + struct nlmsghdr* header = (struct nlmsghdr*)&buf[0]; + size_t header_size = (size_t)amount_read; + for ( ; NLMSG_OK(header, header_size); + header = NLMSG_NEXT(header, header_size)) { + switch (header->nlmsg_type) { + case NLMSG_DONE: + /* Success. Return. */ + *result = start; + close(fd); + return 0; + case NLMSG_ERROR: + close(fd); + android_freeifaddrs(start); + return -1; + case RTM_NEWADDR: { + struct ifaddrmsg* address_msg = + (struct ifaddrmsg*)NLMSG_DATA(header); + struct rtattr* rta = IFA_RTA(address_msg); + ssize_t payload_len = IFA_PAYLOAD(header); + while (RTA_OK(rta, payload_len)) { + if (rta->rta_type == IFA_ADDRESS) { + int family = address_msg->ifa_family; + if (family == AF_INET || family == AF_INET6) { + struct ifaddrs* newest = malloc(sizeof(struct ifaddrs)); + memset(newest, 0, sizeof(struct ifaddrs)); + if (current) { + current->ifa_next = newest; + } else { + start = newest; + } + if (populate_ifaddrs(newest, address_msg, RTA_DATA(rta), + RTA_PAYLOAD(rta)) != 0) { + android_freeifaddrs(start); + *result = NULL; + return -1; + } + current = newest; + } + } + rta = RTA_NEXT(rta, payload_len); + } + break; + } + } + } + amount_read = recv(fd, &buf, kMaxReadSize, 0); + } + close(fd); + android_freeifaddrs(start); + return -1; +} + +void android_freeifaddrs(struct ifaddrs* addrs) { + struct ifaddrs* last = NULL; + struct ifaddrs* cursor = addrs; + while (cursor) { + free(cursor->ifa_name); + free(cursor->ifa_addr); + free(cursor->ifa_netmask); + last = cursor; + cursor = cursor->ifa_next; + free(last); + } +} + +#endif /* defined(ANDROID) */ diff --git a/media/mtransport/third_party/nICEr/src/stun/ifaddrs-android.h b/media/mtransport/third_party/nICEr/src/stun/ifaddrs-android.h new file mode 100644 index 00000000000..5ba174ce65c --- /dev/null +++ b/media/mtransport/third_party/nICEr/src/stun/ifaddrs-android.h @@ -0,0 +1,57 @@ +/* +Copyright (c) 2011, The WebRTC project authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Google nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef WEBRTC_BASE_IFADDRS_ANDROID_H_ +#define WEBRTC_BASE_IFADDRS_ANDROID_H_ + +#include +#include + +/* Implementation of getifaddrs for Android. + * Fills out a list of ifaddr structs (see below) which contain information + * about every network interface available on the host. + * See 'man getifaddrs' on Linux or OS X (nb: it is not a POSIX function). */ +struct ifaddrs { + struct ifaddrs* ifa_next; + char* ifa_name; + unsigned int ifa_flags; + struct sockaddr* ifa_addr; + struct sockaddr* ifa_netmask; + /* Real ifaddrs has broadcast, point to point and data members. + * We don't need them (yet?). */ +}; + +int android_getifaddrs(struct ifaddrs** result); +void android_freeifaddrs(struct ifaddrs* addrs); + +#endif /* WEBRTC_BASE_IFADDRS_ANDROID_H_ */ + diff --git a/media/mtransport/third_party/nICEr/src/stun/stun_codec.c b/media/mtransport/third_party/nICEr/src/stun/stun_codec.c index 1e3a6015d7e..8fb02deeef2 100644 --- a/media/mtransport/third_party/nICEr/src/stun/stun_codec.c +++ b/media/mtransport/third_party/nICEr/src/stun/stun_codec.c @@ -446,9 +446,15 @@ nr_stun_attr_codec_addr_encode(nr_stun_attr_info *attr_info, void *data, int off break; case NR_IPV6: - assert(0); - ABORT(R_INTERNAL); + family = NR_STUN_IPV6_FAMILY; + if (nr_stun_encode_htons(20 , buflen, buf, &offset) + || nr_stun_encode(&pad, 1 , buflen, buf, &offset) + || nr_stun_encode(&family, 1 , buflen, buf, &offset) + || nr_stun_encode_htons(ntohs(addr->u.addr6.sin6_port), buflen, buf, &offset) + || nr_stun_encode(addr->u.addr6.sin6_addr.s6_addr, 16, buflen, buf, &offset)) + ABORT(R_FAILED); break; + default: assert(0); ABORT(R_INTERNAL); @@ -470,6 +476,7 @@ nr_stun_attr_codec_addr_decode(nr_stun_attr_info *attr_info, int attrlen, UCHAR UCHAR family; UINT2 port; UINT4 addr4; + struct in6_addr addr6; nr_transport_addr *result = data; if (nr_stun_decode(1, buf, buflen, &offset, &pad) @@ -492,17 +499,17 @@ nr_stun_attr_codec_addr_decode(nr_stun_attr_info *attr_info, int attrlen, UCHAR break; case NR_STUN_IPV6_FAMILY: - if (attrlen != 16) { + if (attrlen != 20) { r_log(NR_LOG_STUN, LOG_WARNING, "Illegal attribute length: %d", attrlen); ABORT(R_FAILED); } - r_log(NR_LOG_STUN, LOG_WARNING, "IPv6 not supported"); -#ifdef NDEBUG - ABORT(SKIP_ATTRIBUTE_DECODE); -#else - UNIMPLEMENTED; -#endif /* NDEBUG */ + if (nr_stun_decode_htons(buf, buflen, &offset, &port) + || nr_stun_decode(16, buf, buflen, &offset, addr6.s6_addr)) + ABORT(R_FAILED); + + if (nr_ip6_port_to_transport_addr(&addr6, port, IPPROTO_UDP, result)) + ABORT(R_FAILED); break; default: @@ -1094,7 +1101,7 @@ nr_stun_attr_codec_xor_mapped_address_encode(nr_stun_attr_info *attr_info, void * message ID for this */ magic_cookie = ntohl(header->magic_cookie); - nr_stun_xor_mapped_address(magic_cookie, &xor_mapped_address->unmasked, &xor_mapped_address->masked); + nr_stun_xor_mapped_address(magic_cookie, header->id, &xor_mapped_address->unmasked, &xor_mapped_address->masked); r_log(NR_LOG_STUN, LOG_DEBUG, "Masked XOR-MAPPED-ADDRESS = %s", xor_mapped_address->masked.as_string); @@ -1123,7 +1130,7 @@ nr_stun_attr_codec_xor_mapped_address_decode(nr_stun_attr_info *attr_info, int a * message ID for this */ magic_cookie = ntohl(header->magic_cookie); - nr_stun_xor_mapped_address(magic_cookie, &xor_mapped_address->masked, &xor_mapped_address->unmasked); + nr_stun_xor_mapped_address(magic_cookie, header->id, &xor_mapped_address->masked, &xor_mapped_address->unmasked); r_log(NR_LOG_STUN, LOG_DEBUG, "Unmasked XOR-MAPPED-ADDRESS = %s", xor_mapped_address->unmasked.as_string); diff --git a/media/mtransport/third_party/nICEr/src/stun/stun_reg.h b/media/mtransport/third_party/nICEr/src/stun/stun_reg.h index 247a1ec2982..2167fcd91be 100644 --- a/media/mtransport/third_party/nICEr/src/stun/stun_reg.h +++ b/media/mtransport/third_party/nICEr/src/stun/stun_reg.h @@ -45,6 +45,7 @@ extern "C" { #define NR_STUN_REG_PREF_CLNT_FINAL_RETRANSMIT_BACKOFF "stun.client.final_retransmit_backoff" #define NR_STUN_REG_PREF_ALLOW_LOOPBACK_ADDRS "stun.allow_loopback" +#define NR_STUN_REG_PREF_ALLOW_LINK_LOCAL_ADDRS "stun.allow_link_local" #define NR_STUN_REG_PREF_ADDRESS_PRFX "stun.address" #define NR_STUN_REG_PREF_SERVER_NAME "stun.server.name" #define NR_STUN_REG_PREF_SERVER_NONCE_SIZE "stun.server.nonce_size" diff --git a/media/mtransport/third_party/nICEr/src/stun/stun_util.c b/media/mtransport/third_party/nICEr/src/stun/stun_util.c index 82e2064c4c8..a881e5f97ed 100644 --- a/media/mtransport/third_party/nICEr/src/stun/stun_util.c +++ b/media/mtransport/third_party/nICEr/src/stun/stun_util.c @@ -71,7 +71,7 @@ nr_stun_startup(void) } int -nr_stun_xor_mapped_address(UINT4 magicCookie, nr_transport_addr *from, nr_transport_addr *to) +nr_stun_xor_mapped_address(UINT4 magicCookie, UINT12 transactionId, nr_transport_addr *from, nr_transport_addr *to) { int _status; @@ -83,8 +83,26 @@ nr_stun_xor_mapped_address(UINT4 magicCookie, nr_transport_addr *from, nr_transp from->protocol, to); break; case NR_IPV6: - assert(0); - ABORT(R_INTERNAL); + { + union { + unsigned char addr[16]; + UINT4 addr32[4]; + } maskedAddr; + + maskedAddr.addr32[0] = htonl(magicCookie); /* Passed in host byte order */ + memcpy(&maskedAddr.addr32[1], transactionId.octet, sizeof(transactionId)); + + /* We now have the mask in network byte order */ + /* Xor the address in network byte order */ + for (int i = 0; i < sizeof(maskedAddr); ++i) { + maskedAddr.addr[i] ^= from->u.addr6.sin6_addr.s6_addr[i]; + } + + nr_ip6_port_to_transport_addr( + (struct in6_addr*)&maskedAddr, + (ntohs(from->u.addr6.sin6_port) ^ (magicCookie>>16)), + from->protocol, to); + } break; default: assert(0); @@ -111,6 +129,7 @@ nr_stun_find_local_addresses(nr_local_addr addrs[], int maxaddrs, int *count) if (*count == 0) { char allow_loopback; + char allow_link_local; if ((r=NR_reg_get_char(NR_STUN_REG_PREF_ALLOW_LOOPBACK_ADDRS, &allow_loopback))) { if (r == R_NOT_FOUND) @@ -119,7 +138,14 @@ nr_stun_find_local_addresses(nr_local_addr addrs[], int maxaddrs, int *count) ABORT(r); } - if ((r=nr_stun_get_addrs(addrs, maxaddrs, !allow_loopback, count))) + if ((r=NR_reg_get_char(NR_STUN_REG_PREF_ALLOW_LINK_LOCAL_ADDRS, &allow_link_local))) { + if (r == R_NOT_FOUND) + allow_link_local = 0; + else + ABORT(r); + } + + if ((r=nr_stun_get_addrs(addrs, maxaddrs, !allow_loopback, !allow_link_local, count))) ABORT(r); goto done; diff --git a/media/mtransport/third_party/nICEr/src/stun/stun_util.h b/media/mtransport/third_party/nICEr/src/stun/stun_util.h index 67a69a5507f..c57e84d12fc 100644 --- a/media/mtransport/third_party/nICEr/src/stun/stun_util.h +++ b/media/mtransport/third_party/nICEr/src/stun/stun_util.h @@ -42,7 +42,7 @@ extern int NR_LOG_STUN; int nr_stun_startup(void); -int nr_stun_xor_mapped_address(UINT4 magicCookie, nr_transport_addr *from, nr_transport_addr *to); +int nr_stun_xor_mapped_address(UINT4 magicCookie, UINT12 transactionId, nr_transport_addr *from, nr_transport_addr *to); int nr_stun_find_local_addresses(nr_local_addr addrs[], int maxaddrs, int *count); diff --git a/media/mtransport/third_party/nrappkit/src/util/util.c b/media/mtransport/third_party/nrappkit/src/util/util.c index 9d5a8ebd3ad..31a245f454c 100644 --- a/media/mtransport/third_party/nrappkit/src/util/util.c +++ b/media/mtransport/third_party/nrappkit/src/util/util.c @@ -724,6 +724,31 @@ inet_ntop6(const unsigned char *src, char *dst, size_t size) } #endif /* INET6 */ +#ifdef WIN32 +/* Not exactly, will forgive stuff like : */ +int inet_pton(int af, const char *src, void *dst) +{ + struct sockaddr_storage ss; + int addrlen = sizeof(ss); + + if (af != AF_INET && af != AF_INET6) { + return -1; + } + + if (!WSAStringToAddressA(src, af, NULL, (struct sockaddr*)&ss, &addrlen)) { + if (af == AF_INET) { + struct sockaddr_in *in = (struct sockaddr_in*)&ss; + memcpy(dst, &in->sin_addr, sizeof(struct in_addr)); + } else { + struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&ss; + memcpy(dst, &in6->sin6_addr, sizeof(struct in6_addr)); + } + return 1; + } + return 0; +} +#endif /* WIN32 */ + #endif #ifdef WIN32 diff --git a/media/mtransport/third_party/nrappkit/src/util/util.h b/media/mtransport/third_party/nrappkit/src/util/util.h index be887ba70a7..869b7286321 100644 --- a/media/mtransport/third_party/nrappkit/src/util/util.h +++ b/media/mtransport/third_party/nrappkit/src/util/util.h @@ -67,6 +67,7 @@ int nr_reg_uint8_fetch_and_check(NR_registry key, UINT8 min, UINT8 max, int log_ #ifdef WIN32 int snprintf(char *buffer, size_t n, const char *format, ...); const char *inet_ntop(int af, const void *src, char *dst, size_t size); +int inet_pton(int af, const char *src, void *dst); #endif #endif diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp index 32ce924d9e4..3aeb4f6f311 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp @@ -376,6 +376,7 @@ PeerConnectionImpl::PeerConnectionImpl(const GlobalObject* aGlobal) , mPrivacyRequested(false) , mSTSThread(nullptr) , mAllowIceLoopback(false) + , mAllowIceLinkLocal(false) , mMedia(nullptr) , mUuidGen(MakeUnique()) , mNumAudioStreams(0) @@ -397,6 +398,8 @@ PeerConnectionImpl::PeerConnectionImpl(const GlobalObject* aGlobal) #if !defined(MOZILLA_EXTERNAL_LINKAGE) mAllowIceLoopback = Preferences::GetBool( "media.peerconnection.ice.loopback", false); + mAllowIceLinkLocal = Preferences::GetBool( + "media.peerconnection.ice.link_local", false); #endif } @@ -732,7 +735,6 @@ PeerConnectionImpl::Initialize(PeerConnectionObserver& aObserver, } mMedia = new PeerConnectionMedia(this); - mMedia->SetAllowIceLoopback(mAllowIceLoopback); // Connect ICE slots. mMedia->SignalIceGatheringStateChange.connect( diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h index 7a0c90136f0..7c7a9f3c28a 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h @@ -287,6 +287,11 @@ public: // Configure the ability to use localhost. void SetAllowIceLoopback(bool val) { mAllowIceLoopback = val; } + bool GetAllowIceLoopback() const { return mAllowIceLoopback; } + + // Configure the ability to use IPV6 link-local addresses. + void SetAllowIceLinkLocal(bool val) { mAllowIceLinkLocal = val; } + bool GetAllowIceLinkLocal() const { return mAllowIceLinkLocal; } // Handle system to allow weak references to be passed through C code virtual const std::string& GetHandle(); @@ -739,6 +744,7 @@ private: #endif bool mAllowIceLoopback; + bool mAllowIceLinkLocal; nsRefPtr mMedia; // The JSEP negotiation session. diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp index cba75c34633..22abf270550 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp @@ -219,7 +219,6 @@ PeerConnectionMedia::PeerConnectionMedia(PeerConnectionImpl *parent) : mParent(parent), mParentHandle(parent->GetHandle()), mParentName(parent->GetName()), - mAllowIceLoopback(false), mIceCtx(nullptr), mDNSResolver(new NrIceResolver()), mUuidGen(MakeUnique()), @@ -311,8 +310,9 @@ nsresult PeerConnectionMedia::Init(const std::vector& stun_serv mIceCtx = NrIceCtx::Create("PC:" + mParentName, true, // Offerer true, // Explicitly set priorities - mAllowIceLoopback, - ice_tcp); + mParent->GetAllowIceLoopback(), + ice_tcp, + mParent->GetAllowIceLinkLocal()); if(!mIceCtx) { CSFLogError(logTag, "%s: Failed to create Ice Context", __FUNCTION__); return NS_ERROR_FAILURE; diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h index 707ab8b8ada..748b651070c 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h @@ -232,9 +232,6 @@ class PeerConnectionMedia : public sigslot::has_slots<> { // WARNING: This destroys the object! void SelfDestruct(); - // Configure the ability to use localhost. - void SetAllowIceLoopback(bool val) { mAllowIceLoopback = val; } - RefPtr ice_ctx() const { return mIceCtx; } RefPtr ice_media_stream(size_t i) const { @@ -491,9 +488,6 @@ class PeerConnectionMedia : public sigslot::has_slots<> { std::map>> mConduits; - // Allow loopback for ICE. - bool mAllowIceLoopback; - // ICE objects RefPtr mIceCtx; diff --git a/media/webrtc/signaling/src/sdp/SdpMediaSection.h b/media/webrtc/signaling/src/sdp/SdpMediaSection.h index 7ec1b029b35..d4faa9334fc 100644 --- a/media/webrtc/signaling/src/sdp/SdpMediaSection.h +++ b/media/webrtc/signaling/src/sdp/SdpMediaSection.h @@ -286,6 +286,11 @@ public: SetAddress(const std::string& address) { mAddr = address; + if (mAddr.find(':') != std::string::npos) { + mAddrType = sdp::kIPv6; + } else { + mAddrType = sdp::kIPv4; + } } uint8_t GetTtl() const diff --git a/media/webrtc/signaling/test/signaling_unittests.cpp b/media/webrtc/signaling/test/signaling_unittests.cpp index 5e4b3361579..77d99adc6f7 100644 --- a/media/webrtc/signaling/test/signaling_unittests.cpp +++ b/media/webrtc/signaling/test/signaling_unittests.cpp @@ -913,6 +913,7 @@ class SignalingAgent { PeerConnectionImpl::CreatePeerConnection(); EXPECT_TRUE(pcImpl); pcImpl->SetAllowIceLoopback(true); + pcImpl->SetAllowIceLinkLocal(true); pc = new PCDispatchWrapper(pcImpl); } @@ -4709,7 +4710,7 @@ int main(int argc, char **argv) { // Adds a listener to the end. Google Test takes the ownership. listeners.Append(new test::RingbufferDumper(test_utils)); test_utils->sts_target()->Dispatch( - WrapRunnableNM(&TestStunServer::GetInstance), NS_DISPATCH_SYNC); + WrapRunnableNM(&TestStunServer::GetInstance, AF_INET), NS_DISPATCH_SYNC); // Set the main thread global which is this thread. nsIThread *thread; diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 4e18b6ba615..04e3a3a6bcc 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -375,6 +375,7 @@ pref("media.navigator.permission.disabled", false); pref("media.peerconnection.default_iceservers", "[]"); pref("media.peerconnection.ice.loopback", false); // Set only for testing in offline environments. pref("media.peerconnection.ice.tcp", false); +pref("media.peerconnection.ice.link_local", false); // Set only for testing IPV6 in networks that don't assign IPV6 addresses pref("media.peerconnection.use_document_iceservers", true); pref("media.peerconnection.identity.enabled", true); pref("media.peerconnection.identity.timeout", 10000);