Reland "Fix problem with ipv4 over ipv6 on Android"
This reverts commit 1e60490ddb11afecc796058802fbc80867d851d8. Reason for revert: Downstream project has been fixed (127.0.0.1 is not PII) Original change's description: > Revert "Fix problem with ipv4 over ipv6 on Android" > > This reverts commit da2fd2a2b25ee4bd7b383424cb26d51fb6cc7716, > as well as follow-up b7227a5a10f233cec04642f15a0233e7355bd340, > "Fix handling of partial match for GetVpnUnderlyingAdapterType". > > Reason for revert: Breaks downstream test. > > First change's description: > > Fix problem with ipv4 over ipv6 on Android > > > > This patch fixes a problem with using ipv4 over ipv6 > > addresses on Android. These addresses are discovered > > using 'getifaddr' with interfaces called 'v4-wlan0' or > > 'v4-rmnet' but the Android API does not report them. > > > > This leads to failure when BasicPortAllocator tries > > to bind a socket to the ip-address, making the ipv4 > > address unusable. > > > > This solution does the following > > 1) Insert BasicNetworkManager as NetworkBinderInterface > > rather than AndroidNetworkManager. > > > > 2) When SocketServer calls BindSocketToNetwork, > > BasicNetworkManager first lookup the interface name, > > and then calls AndroidNetworkManager. > > > > 3) AndroidNetworkManager will then first try to bind > > using the known ip-addresses, and if it can't find the network > > it will instead match the interface names. > > > > The patch has been tested on real android devices, and works fine. > > And everything is disabled by default, and is enabled by field trial. > > > > My plan is to rollout the feature, checking that it does not introduce > > any problems, and if so, enabled for all. > > > > Bug: webrtc:10707 > > Change-Id: I7081ba43d4ce17077acfa5fbab44eda127ac3971 > > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/211003 > > Commit-Queue: Jonas Oreland <jonaso@webrtc.org> > > Reviewed-by: Harald Alvestrand <hta@webrtc.org> > > Cr-Commit-Position: refs/heads/master@{#33422} > > Second change's description: > > Fix handling of partial match for GetVpnUnderlyingAdapterType > > > > This is a followup to https://webrtc-review.googlesource.com/c/src/+/211003 > > and fixes the problem pointed out by deadbeef@, thanks! > > > > Bug: webrtc:10707 > > Change-Id: I8dea842b25ba15416353ce4002356183087873c7 > > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/211344 > > Commit-Queue: Jonas Oreland <jonaso@webrtc.org> > > Reviewed-by: Harald Alvestrand <hta@webrtc.org> > > Cr-Commit-Position: refs/heads/master@{#33436} > > TBR=hta@webrtc.org,jonaso@webrtc.org > NOTRY=True > > Bug: webrtc:10707 > Change-Id: Ib13127fbf087c7f34ca0ccc6ce1805706f01d19d > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/211740 > Reviewed-by: Taylor <deadbeef@webrtc.org> > Commit-Queue: Taylor <deadbeef@webrtc.org> > Cr-Commit-Position: refs/heads/master@{#33453} # Not skipping CQ checks because original CL landed > 1 day ago. Bug: webrtc:10707 Change-Id: I0a11025c366c3127e2f57cd2cd2c33cc3877d1e3 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/211862 Reviewed-by: Harald Alvestrand <hta@webrtc.org> Reviewed-by: Jonas Oreland <jonaso@webrtc.org> Commit-Queue: Jonas Oreland <jonaso@webrtc.org> Cr-Commit-Position: refs/heads/master@{#33460}
This commit is contained in:
parent
7087b83d80
commit
6ca955a1dd
@ -212,7 +212,8 @@ AdapterType GetAdapterTypeFromName(const char* network_name) {
|
|||||||
return ADAPTER_TYPE_ETHERNET;
|
return ADAPTER_TYPE_ETHERNET;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MatchTypeNameWithIndexPattern(network_name, "wlan")) {
|
if (MatchTypeNameWithIndexPattern(network_name, "wlan") ||
|
||||||
|
MatchTypeNameWithIndexPattern(network_name, "v4-wlan")) {
|
||||||
return ADAPTER_TYPE_WIFI;
|
return ADAPTER_TYPE_WIFI;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -478,15 +479,15 @@ Network* NetworkManagerBase::GetNetworkFromAddress(
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicNetworkManager::BasicNetworkManager()
|
BasicNetworkManager::BasicNetworkManager() : BasicNetworkManager(nullptr) {}
|
||||||
: allow_mac_based_ipv6_(
|
|
||||||
webrtc::field_trial::IsEnabled("WebRTC-AllowMACBasedIPv6")) {}
|
|
||||||
|
|
||||||
BasicNetworkManager::BasicNetworkManager(
|
BasicNetworkManager::BasicNetworkManager(
|
||||||
NetworkMonitorFactory* network_monitor_factory)
|
NetworkMonitorFactory* network_monitor_factory)
|
||||||
: network_monitor_factory_(network_monitor_factory),
|
: network_monitor_factory_(network_monitor_factory),
|
||||||
allow_mac_based_ipv6_(
|
allow_mac_based_ipv6_(
|
||||||
webrtc::field_trial::IsEnabled("WebRTC-AllowMACBasedIPv6")) {}
|
webrtc::field_trial::IsEnabled("WebRTC-AllowMACBasedIPv6")),
|
||||||
|
bind_using_ifname_(
|
||||||
|
webrtc::field_trial::IsEnabled("WebRTC-BindUsingInterfaceName")) {}
|
||||||
|
|
||||||
BasicNetworkManager::~BasicNetworkManager() {}
|
BasicNetworkManager::~BasicNetworkManager() {}
|
||||||
|
|
||||||
@ -865,6 +866,15 @@ void BasicNetworkManager::StartNetworkMonitor() {
|
|||||||
network_monitor_->SignalNetworksChanged.connect(
|
network_monitor_->SignalNetworksChanged.connect(
|
||||||
this, &BasicNetworkManager::OnNetworksChanged);
|
this, &BasicNetworkManager::OnNetworksChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (network_monitor_->SupportsBindSocketToNetwork()) {
|
||||||
|
// Set NetworkBinder on SocketServer so that
|
||||||
|
// PhysicalSocket::Bind will call
|
||||||
|
// BasicNetworkManager::BindSocketToNetwork(), (that will lookup interface
|
||||||
|
// name and then call network_monitor_->BindSocketToNetwork()).
|
||||||
|
thread_->socketserver()->set_network_binder(this);
|
||||||
|
}
|
||||||
|
|
||||||
network_monitor_->Start();
|
network_monitor_->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -873,6 +883,13 @@ void BasicNetworkManager::StopNetworkMonitor() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
network_monitor_->Stop();
|
network_monitor_->Stop();
|
||||||
|
|
||||||
|
if (network_monitor_->SupportsBindSocketToNetwork()) {
|
||||||
|
// Reset NetworkBinder on SocketServer.
|
||||||
|
if (thread_->socketserver()->network_binder() == this) {
|
||||||
|
thread_->socketserver()->set_network_binder(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BasicNetworkManager::OnMessage(Message* msg) {
|
void BasicNetworkManager::OnMessage(Message* msg) {
|
||||||
@ -954,6 +971,20 @@ void BasicNetworkManager::DumpNetworks() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetworkBindingResult BasicNetworkManager::BindSocketToNetwork(
|
||||||
|
int socket_fd,
|
||||||
|
const IPAddress& address) {
|
||||||
|
RTC_DCHECK_RUN_ON(thread_);
|
||||||
|
std::string if_name;
|
||||||
|
if (bind_using_ifname_) {
|
||||||
|
Network* net = GetNetworkFromAddress(address);
|
||||||
|
if (net != nullptr) {
|
||||||
|
if_name = net->name();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return network_monitor_->BindSocketToNetwork(socket_fd, address, if_name);
|
||||||
|
}
|
||||||
|
|
||||||
Network::Network(const std::string& name,
|
Network::Network(const std::string& name,
|
||||||
const std::string& desc,
|
const std::string& desc,
|
||||||
const IPAddress& prefix,
|
const IPAddress& prefix,
|
||||||
|
|||||||
@ -194,11 +194,11 @@ class RTC_EXPORT NetworkManagerBase : public NetworkManager {
|
|||||||
void set_default_local_addresses(const IPAddress& ipv4,
|
void set_default_local_addresses(const IPAddress& ipv4,
|
||||||
const IPAddress& ipv6);
|
const IPAddress& ipv6);
|
||||||
|
|
||||||
|
Network* GetNetworkFromAddress(const rtc::IPAddress& ip) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class NetworkTest;
|
friend class NetworkTest;
|
||||||
|
|
||||||
Network* GetNetworkFromAddress(const rtc::IPAddress& ip) const;
|
|
||||||
|
|
||||||
EnumerationPermission enumeration_permission_;
|
EnumerationPermission enumeration_permission_;
|
||||||
|
|
||||||
NetworkList networks_;
|
NetworkList networks_;
|
||||||
@ -225,6 +225,7 @@ class RTC_EXPORT NetworkManagerBase : public NetworkManager {
|
|||||||
// of networks using OS APIs.
|
// of networks using OS APIs.
|
||||||
class RTC_EXPORT BasicNetworkManager : public NetworkManagerBase,
|
class RTC_EXPORT BasicNetworkManager : public NetworkManagerBase,
|
||||||
public MessageHandlerAutoCleanup,
|
public MessageHandlerAutoCleanup,
|
||||||
|
public NetworkBinderInterface,
|
||||||
public sigslot::has_slots<> {
|
public sigslot::has_slots<> {
|
||||||
public:
|
public:
|
||||||
BasicNetworkManager();
|
BasicNetworkManager();
|
||||||
@ -248,6 +249,15 @@ class RTC_EXPORT BasicNetworkManager : public NetworkManagerBase,
|
|||||||
network_ignore_list_ = list;
|
network_ignore_list_ = list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bind a socket to interface that ip address belong to.
|
||||||
|
// Implementation look up interface name and calls
|
||||||
|
// BindSocketToNetwork on NetworkMonitor.
|
||||||
|
// The interface name is needed as e.g ipv4 over ipv6 addresses
|
||||||
|
// are not exposed using Android functions, but it is possible
|
||||||
|
// bind an ipv4 address to the interface.
|
||||||
|
NetworkBindingResult BindSocketToNetwork(int socket_fd,
|
||||||
|
const IPAddress& address) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
#if defined(WEBRTC_POSIX)
|
#if defined(WEBRTC_POSIX)
|
||||||
// Separated from CreateNetworks for tests.
|
// Separated from CreateNetworks for tests.
|
||||||
@ -293,7 +303,8 @@ class RTC_EXPORT BasicNetworkManager : public NetworkManagerBase,
|
|||||||
nullptr;
|
nullptr;
|
||||||
std::unique_ptr<NetworkMonitorInterface> network_monitor_
|
std::unique_ptr<NetworkMonitorInterface> network_monitor_
|
||||||
RTC_GUARDED_BY(thread_);
|
RTC_GUARDED_BY(thread_);
|
||||||
bool allow_mac_based_ipv6_ = false;
|
bool allow_mac_based_ipv6_ RTC_GUARDED_BY(thread_) = false;
|
||||||
|
bool bind_using_ifname_ RTC_GUARDED_BY(thread_) = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Represents a Unix-type network interface, with a name and single address.
|
// Represents a Unix-type network interface, with a name and single address.
|
||||||
|
|||||||
@ -36,6 +36,8 @@ enum class NetworkPreference {
|
|||||||
|
|
||||||
const char* NetworkPreferenceToString(NetworkPreference preference);
|
const char* NetworkPreferenceToString(NetworkPreference preference);
|
||||||
|
|
||||||
|
// This interface is set onto a socket server,
|
||||||
|
// where only the ip address is known at the time of binding.
|
||||||
class NetworkBinderInterface {
|
class NetworkBinderInterface {
|
||||||
public:
|
public:
|
||||||
// Binds a socket to the network that is attached to |address| so that all
|
// Binds a socket to the network that is attached to |address| so that all
|
||||||
@ -83,6 +85,19 @@ class NetworkMonitorInterface {
|
|||||||
virtual NetworkPreference GetNetworkPreference(
|
virtual NetworkPreference GetNetworkPreference(
|
||||||
const std::string& interface_name) = 0;
|
const std::string& interface_name) = 0;
|
||||||
|
|
||||||
|
// Does |this| NetworkMonitorInterface implement BindSocketToNetwork?
|
||||||
|
// Only Android returns true.
|
||||||
|
virtual bool SupportsBindSocketToNetwork() const { return false; }
|
||||||
|
|
||||||
|
// Bind a socket to an interface specified by ip address and/or interface
|
||||||
|
// name. Only implemented on Android.
|
||||||
|
virtual NetworkBindingResult BindSocketToNetwork(
|
||||||
|
int socket_fd,
|
||||||
|
const IPAddress& address,
|
||||||
|
const std::string& interface_name) {
|
||||||
|
return NetworkBindingResult::NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
// Is this interface available to use? WebRTC shouldn't attempt to use it if
|
// Is this interface available to use? WebRTC shouldn't attempt to use it if
|
||||||
// this returns false.
|
// this returns false.
|
||||||
//
|
//
|
||||||
|
|||||||
@ -76,9 +76,35 @@ class FakeNetworkMonitor : public NetworkMonitorInterface {
|
|||||||
unavailable_adapters_ = unavailable_adapters;
|
unavailable_adapters_ = unavailable_adapters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SupportsBindSocketToNetwork() const override { return true; }
|
||||||
|
|
||||||
|
NetworkBindingResult BindSocketToNetwork(
|
||||||
|
int socket_fd,
|
||||||
|
const IPAddress& address,
|
||||||
|
const std::string& if_name) override {
|
||||||
|
if (absl::c_count(addresses_, address) > 0) {
|
||||||
|
return NetworkBindingResult::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto const& iter : adapters_) {
|
||||||
|
if (if_name.find(iter) != std::string::npos) {
|
||||||
|
return NetworkBindingResult::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NetworkBindingResult::ADDRESS_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_ip_addresses(std::vector<IPAddress> addresses) {
|
||||||
|
addresses_ = addresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_adapters(std::vector<std::string> adapters) { adapters_ = adapters; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool started_ = false;
|
bool started_ = false;
|
||||||
|
std::vector<std::string> adapters_;
|
||||||
std::vector<std::string> unavailable_adapters_;
|
std::vector<std::string> unavailable_adapters_;
|
||||||
|
std::vector<IPAddress> addresses_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FakeNetworkMonitorFactory : public NetworkMonitorFactory {
|
class FakeNetworkMonitorFactory : public NetworkMonitorFactory {
|
||||||
@ -1279,4 +1305,48 @@ TEST_F(NetworkTest, WebRTC_AllowMACBasedIPv6Address) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(WEBRTC_POSIX)
|
||||||
|
TEST_F(NetworkTest, WebRTC_BindUsingInterfaceName) {
|
||||||
|
webrtc::test::ScopedFieldTrials field_trials(
|
||||||
|
"WebRTC-BindUsingInterfaceName/Enabled/");
|
||||||
|
|
||||||
|
char if_name1[20] = "wlan0";
|
||||||
|
char if_name2[20] = "v4-wlan0";
|
||||||
|
ifaddrs* list = nullptr;
|
||||||
|
list = AddIpv6Address(list, if_name1, "1000:2000:3000:4000:0:0:0:1",
|
||||||
|
"FFFF:FFFF:FFFF:FFFF::", 0);
|
||||||
|
list = AddIpv4Address(list, if_name2, "192.168.0.2", "255.255.255.255");
|
||||||
|
NetworkManager::NetworkList result;
|
||||||
|
|
||||||
|
// Sanity check that both interfaces are included by default.
|
||||||
|
FakeNetworkMonitorFactory factory;
|
||||||
|
BasicNetworkManager manager(&factory);
|
||||||
|
manager.StartUpdating();
|
||||||
|
CallConvertIfAddrs(manager, list, /*include_ignored=*/false, &result);
|
||||||
|
EXPECT_EQ(2u, result.size());
|
||||||
|
ReleaseIfAddrs(list);
|
||||||
|
bool changed;
|
||||||
|
// This ensures we release the objects created in CallConvertIfAddrs.
|
||||||
|
MergeNetworkList(manager, result, &changed);
|
||||||
|
result.clear();
|
||||||
|
|
||||||
|
FakeNetworkMonitor* network_monitor = GetNetworkMonitor(manager);
|
||||||
|
|
||||||
|
IPAddress ipv6;
|
||||||
|
EXPECT_TRUE(IPFromString("1000:2000:3000:4000:0:0:0:1", &ipv6));
|
||||||
|
IPAddress ipv4;
|
||||||
|
EXPECT_TRUE(IPFromString("192.168.0.2", &ipv4));
|
||||||
|
|
||||||
|
// The network monitor only knwos about the ipv6 address, interface.
|
||||||
|
network_monitor->set_adapters({"wlan0"});
|
||||||
|
network_monitor->set_ip_addresses({ipv6});
|
||||||
|
EXPECT_EQ(manager.BindSocketToNetwork(/* fd */ 77, ipv6),
|
||||||
|
NetworkBindingResult::SUCCESS);
|
||||||
|
|
||||||
|
// But it will bind anyway using string matching...
|
||||||
|
EXPECT_EQ(manager.BindSocketToNetwork(/* fd */ 77, ipv4),
|
||||||
|
NetworkBindingResult::SUCCESS);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace rtc
|
} // namespace rtc
|
||||||
|
|||||||
@ -74,7 +74,7 @@ TEST_F(AndroidNetworkMonitorTest, TestFindNetworkHandleUsingIpv4Address) {
|
|||||||
network_monitor_->SetNetworkInfos(net_infos);
|
network_monitor_->SetNetworkInfos(net_infos);
|
||||||
|
|
||||||
auto network_handle =
|
auto network_handle =
|
||||||
network_monitor_->FindNetworkHandleFromAddress(ipv4_address);
|
network_monitor_->FindNetworkHandleFromAddressOrName(ipv4_address, "");
|
||||||
|
|
||||||
ASSERT_TRUE(network_handle.has_value());
|
ASSERT_TRUE(network_handle.has_value());
|
||||||
EXPECT_EQ(ipv4_handle, *network_handle);
|
EXPECT_EQ(ipv4_handle, *network_handle);
|
||||||
@ -91,9 +91,9 @@ TEST_F(AndroidNetworkMonitorTest, TestFindNetworkHandleUsingFullIpv6Address) {
|
|||||||
network_monitor_->SetNetworkInfos(net_infos);
|
network_monitor_->SetNetworkInfos(net_infos);
|
||||||
|
|
||||||
auto network_handle1 =
|
auto network_handle1 =
|
||||||
network_monitor_->FindNetworkHandleFromAddress(ipv6_address1);
|
network_monitor_->FindNetworkHandleFromAddressOrName(ipv6_address1, "");
|
||||||
auto network_handle2 =
|
auto network_handle2 =
|
||||||
network_monitor_->FindNetworkHandleFromAddress(ipv6_address2);
|
network_monitor_->FindNetworkHandleFromAddressOrName(ipv6_address2, "");
|
||||||
|
|
||||||
ASSERT_TRUE(network_handle1.has_value());
|
ASSERT_TRUE(network_handle1.has_value());
|
||||||
EXPECT_EQ(ipv6_handle, *network_handle1);
|
EXPECT_EQ(ipv6_handle, *network_handle1);
|
||||||
@ -116,9 +116,9 @@ TEST_F(AndroidNetworkMonitorTest,
|
|||||||
network_monitor_->SetNetworkInfos(net_infos);
|
network_monitor_->SetNetworkInfos(net_infos);
|
||||||
|
|
||||||
auto network_handle1 =
|
auto network_handle1 =
|
||||||
network_monitor_->FindNetworkHandleFromAddress(ipv6_address1);
|
network_monitor_->FindNetworkHandleFromAddressOrName(ipv6_address1, "");
|
||||||
auto network_handle2 =
|
auto network_handle2 =
|
||||||
network_monitor_->FindNetworkHandleFromAddress(ipv6_address2);
|
network_monitor_->FindNetworkHandleFromAddressOrName(ipv6_address2, "");
|
||||||
|
|
||||||
ASSERT_TRUE(network_handle1.has_value());
|
ASSERT_TRUE(network_handle1.has_value());
|
||||||
EXPECT_EQ(ipv6_handle, *network_handle1);
|
EXPECT_EQ(ipv6_handle, *network_handle1);
|
||||||
@ -126,5 +126,47 @@ TEST_F(AndroidNetworkMonitorTest,
|
|||||||
EXPECT_EQ(ipv6_handle, *network_handle2);
|
EXPECT_EQ(ipv6_handle, *network_handle2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(AndroidNetworkMonitorTest, TestFindNetworkHandleUsingIfName) {
|
||||||
|
ScopedFieldTrials field_trials("WebRTC-BindUsingInterfaceName/Enabled/");
|
||||||
|
// Start() updates the states introduced by the field trial.
|
||||||
|
network_monitor_->Start();
|
||||||
|
jni::NetworkHandle ipv6_handle = 200;
|
||||||
|
rtc::IPAddress ipv6_address1 = GetIpAddressFromIpv6String(kTestIpv6Address1);
|
||||||
|
|
||||||
|
// Set up an IPv6 network.
|
||||||
|
jni::NetworkInformation net_info =
|
||||||
|
CreateNetworkInformation("wlan0", ipv6_handle, ipv6_address1);
|
||||||
|
std::vector<jni::NetworkInformation> net_infos(1, net_info);
|
||||||
|
network_monitor_->SetNetworkInfos(net_infos);
|
||||||
|
|
||||||
|
rtc::IPAddress ipv4_address(kTestIpv4Address);
|
||||||
|
|
||||||
|
// Search using ip address only...
|
||||||
|
auto network_handle1 =
|
||||||
|
network_monitor_->FindNetworkHandleFromAddressOrName(ipv4_address, "");
|
||||||
|
|
||||||
|
// Search using ip address AND if_name (for typical ipv4 over ipv6 tunnel).
|
||||||
|
auto network_handle2 = network_monitor_->FindNetworkHandleFromAddressOrName(
|
||||||
|
ipv4_address, "v4-wlan0");
|
||||||
|
|
||||||
|
ASSERT_FALSE(network_handle1.has_value());
|
||||||
|
ASSERT_TRUE(network_handle2.has_value());
|
||||||
|
EXPECT_EQ(ipv6_handle, *network_handle2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(AndroidNetworkMonitorTest, TestUnderlyingVpnType) {
|
||||||
|
ScopedFieldTrials field_trials("WebRTC-BindUsingInterfaceName/Enabled/");
|
||||||
|
jni::NetworkHandle ipv4_handle = 100;
|
||||||
|
rtc::IPAddress ipv4_address(kTestIpv4Address);
|
||||||
|
jni::NetworkInformation net_info =
|
||||||
|
CreateNetworkInformation("wlan0", ipv4_handle, ipv4_address);
|
||||||
|
net_info.type = jni::NETWORK_VPN;
|
||||||
|
net_info.underlying_type_for_vpn = jni::NETWORK_WIFI;
|
||||||
|
network_monitor_->SetNetworkInfos({net_info});
|
||||||
|
|
||||||
|
EXPECT_EQ(rtc::ADAPTER_TYPE_WIFI,
|
||||||
|
network_monitor_->GetVpnUnderlyingAdapterType("v4-wlan0"));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace test
|
} // namespace test
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -247,11 +247,8 @@ void AndroidNetworkMonitor::Start() {
|
|||||||
find_network_handle_without_ipv6_temporary_part_ =
|
find_network_handle_without_ipv6_temporary_part_ =
|
||||||
webrtc::field_trial::IsEnabled(
|
webrtc::field_trial::IsEnabled(
|
||||||
"WebRTC-FindNetworkHandleWithoutIpv6TemporaryPart");
|
"WebRTC-FindNetworkHandleWithoutIpv6TemporaryPart");
|
||||||
|
bind_using_ifname_ =
|
||||||
// This is kind of magic behavior, but doing this allows the SocketServer to
|
webrtc::field_trial::IsEnabled("WebRTC-BindUsingInterfaceName");
|
||||||
// use this as a NetworkBinder to bind sockets on a particular network when
|
|
||||||
// it creates sockets.
|
|
||||||
network_thread_->socketserver()->set_network_binder(this);
|
|
||||||
|
|
||||||
// Needed for restart after Stop().
|
// Needed for restart after Stop().
|
||||||
safety_flag_->SetAlive();
|
safety_flag_->SetAlive();
|
||||||
@ -285,7 +282,8 @@ void AndroidNetworkMonitor::Stop() {
|
|||||||
// https://cs.chromium.org/chromium/src/net/udp/udp_socket_posix.cc
|
// https://cs.chromium.org/chromium/src/net/udp/udp_socket_posix.cc
|
||||||
rtc::NetworkBindingResult AndroidNetworkMonitor::BindSocketToNetwork(
|
rtc::NetworkBindingResult AndroidNetworkMonitor::BindSocketToNetwork(
|
||||||
int socket_fd,
|
int socket_fd,
|
||||||
const rtc::IPAddress& address) {
|
const rtc::IPAddress& address,
|
||||||
|
const std::string& if_name) {
|
||||||
RTC_DCHECK_RUN_ON(network_thread_);
|
RTC_DCHECK_RUN_ON(network_thread_);
|
||||||
|
|
||||||
// Android prior to Lollipop didn't have support for binding sockets to
|
// Android prior to Lollipop didn't have support for binding sockets to
|
||||||
@ -303,12 +301,18 @@ rtc::NetworkBindingResult AndroidNetworkMonitor::BindSocketToNetwork(
|
|||||||
}
|
}
|
||||||
|
|
||||||
absl::optional<NetworkHandle> network_handle =
|
absl::optional<NetworkHandle> network_handle =
|
||||||
FindNetworkHandleFromAddress(address);
|
FindNetworkHandleFromAddressOrName(address, if_name);
|
||||||
if (!network_handle) {
|
if (!network_handle) {
|
||||||
|
RTC_LOG(LS_WARNING)
|
||||||
|
<< "BindSocketToNetwork unable to find network handle for"
|
||||||
|
<< " addr: " << address.ToSensitiveString() << " ifname: " << if_name;
|
||||||
return rtc::NetworkBindingResult::ADDRESS_NOT_FOUND;
|
return rtc::NetworkBindingResult::ADDRESS_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*network_handle == 0 /* NETWORK_UNSPECIFIED */) {
|
if (*network_handle == 0 /* NETWORK_UNSPECIFIED */) {
|
||||||
|
RTC_LOG(LS_WARNING) << "BindSocketToNetwork 0 network handle for"
|
||||||
|
<< " addr: " << address.ToSensitiveString()
|
||||||
|
<< " ifname: " << if_name;
|
||||||
return rtc::NetworkBindingResult::NOT_IMPLEMENTED;
|
return rtc::NetworkBindingResult::NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,11 +379,19 @@ rtc::NetworkBindingResult AndroidNetworkMonitor::BindSocketToNetwork(
|
|||||||
// ERR_NETWORK_CHANGED, rather than MapSystemError(ENONET) which gives back
|
// ERR_NETWORK_CHANGED, rather than MapSystemError(ENONET) which gives back
|
||||||
// the less descriptive ERR_FAILED.
|
// the less descriptive ERR_FAILED.
|
||||||
if (rv == 0) {
|
if (rv == 0) {
|
||||||
|
RTC_LOG(LS_VERBOSE) << "BindSocketToNetwork bound network handle for"
|
||||||
|
<< " addr: " << address.ToSensitiveString()
|
||||||
|
<< " ifname: " << if_name;
|
||||||
return rtc::NetworkBindingResult::SUCCESS;
|
return rtc::NetworkBindingResult::SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RTC_LOG(LS_WARNING) << "BindSocketToNetwork got error: " << rv
|
||||||
|
<< " addr: " << address.ToSensitiveString()
|
||||||
|
<< " ifname: " << if_name;
|
||||||
if (rv == ENONET) {
|
if (rv == ENONET) {
|
||||||
return rtc::NetworkBindingResult::NETWORK_CHANGED;
|
return rtc::NetworkBindingResult::NETWORK_CHANGED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rtc::NetworkBindingResult::FAILURE;
|
return rtc::NetworkBindingResult::FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,8 +414,9 @@ void AndroidNetworkMonitor::OnNetworkConnected_n(
|
|||||||
}
|
}
|
||||||
|
|
||||||
absl::optional<NetworkHandle>
|
absl::optional<NetworkHandle>
|
||||||
AndroidNetworkMonitor::FindNetworkHandleFromAddress(
|
AndroidNetworkMonitor::FindNetworkHandleFromAddressOrName(
|
||||||
const rtc::IPAddress& ip_address) const {
|
const rtc::IPAddress& ip_address,
|
||||||
|
const std::string& if_name) const {
|
||||||
RTC_DCHECK_RUN_ON(network_thread_);
|
RTC_DCHECK_RUN_ON(network_thread_);
|
||||||
RTC_LOG(LS_INFO) << "Find network handle.";
|
RTC_LOG(LS_INFO) << "Find network handle.";
|
||||||
if (find_network_handle_without_ipv6_temporary_part_) {
|
if (find_network_handle_without_ipv6_temporary_part_) {
|
||||||
@ -417,16 +430,33 @@ AndroidNetworkMonitor::FindNetworkHandleFromAddress(
|
|||||||
return absl::make_optional(iter.first);
|
return absl::make_optional(iter.first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return absl::nullopt;
|
|
||||||
} else {
|
} else {
|
||||||
auto iter = network_handle_by_address_.find(ip_address);
|
auto iter = network_handle_by_address_.find(ip_address);
|
||||||
if (iter == network_handle_by_address_.end()) {
|
if (iter != network_handle_by_address_.end()) {
|
||||||
return absl::nullopt;
|
|
||||||
}
|
|
||||||
return absl::make_optional(iter->second);
|
return absl::make_optional(iter->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return FindNetworkHandleFromIfname(if_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::optional<NetworkHandle>
|
||||||
|
AndroidNetworkMonitor::FindNetworkHandleFromIfname(
|
||||||
|
const std::string& if_name) const {
|
||||||
|
RTC_DCHECK_RUN_ON(network_thread_);
|
||||||
|
if (bind_using_ifname_) {
|
||||||
|
for (auto const& iter : network_info_by_handle_) {
|
||||||
|
if (if_name.find(iter.second.interface_name) != std::string::npos) {
|
||||||
|
// Use partial match so that e.g if_name="v4-wlan0" is matched
|
||||||
|
// agains iter.first="wlan0"
|
||||||
|
return absl::make_optional(iter.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return absl::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
void AndroidNetworkMonitor::OnNetworkDisconnected_n(NetworkHandle handle) {
|
void AndroidNetworkMonitor::OnNetworkDisconnected_n(NetworkHandle handle) {
|
||||||
RTC_DCHECK_RUN_ON(network_thread_);
|
RTC_DCHECK_RUN_ON(network_thread_);
|
||||||
RTC_LOG(LS_INFO) << "Network disconnected for handle " << handle;
|
RTC_LOG(LS_INFO) << "Network disconnected for handle " << handle;
|
||||||
@ -470,6 +500,18 @@ rtc::AdapterType AndroidNetworkMonitor::GetAdapterType(
|
|||||||
rtc::AdapterType type = (iter == adapter_type_by_name_.end())
|
rtc::AdapterType type = (iter == adapter_type_by_name_.end())
|
||||||
? rtc::ADAPTER_TYPE_UNKNOWN
|
? rtc::ADAPTER_TYPE_UNKNOWN
|
||||||
: iter->second;
|
: iter->second;
|
||||||
|
|
||||||
|
if (type == rtc::ADAPTER_TYPE_UNKNOWN && bind_using_ifname_) {
|
||||||
|
for (auto const& iter : adapter_type_by_name_) {
|
||||||
|
// Use partial match so that e.g if_name="v4-wlan0" is matched
|
||||||
|
// agains iter.first="wlan0"
|
||||||
|
if (if_name.find(iter.first) != std::string::npos) {
|
||||||
|
type = iter.second;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (type == rtc::ADAPTER_TYPE_UNKNOWN) {
|
if (type == rtc::ADAPTER_TYPE_UNKNOWN) {
|
||||||
RTC_LOG(LS_WARNING) << "Get an unknown type for the interface " << if_name;
|
RTC_LOG(LS_WARNING) << "Get an unknown type for the interface " << if_name;
|
||||||
}
|
}
|
||||||
@ -483,6 +525,17 @@ rtc::AdapterType AndroidNetworkMonitor::GetVpnUnderlyingAdapterType(
|
|||||||
rtc::AdapterType type = (iter == vpn_underlying_adapter_type_by_name_.end())
|
rtc::AdapterType type = (iter == vpn_underlying_adapter_type_by_name_.end())
|
||||||
? rtc::ADAPTER_TYPE_UNKNOWN
|
? rtc::ADAPTER_TYPE_UNKNOWN
|
||||||
: iter->second;
|
: iter->second;
|
||||||
|
if (type == rtc::ADAPTER_TYPE_UNKNOWN && bind_using_ifname_) {
|
||||||
|
// Use partial match so that e.g if_name="v4-wlan0" is matched
|
||||||
|
// agains iter.first="wlan0"
|
||||||
|
for (auto const& iter : vpn_underlying_adapter_type_by_name_) {
|
||||||
|
if (if_name.find(iter.first) != std::string::npos) {
|
||||||
|
type = iter.second;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -64,8 +64,7 @@ struct NetworkInformation {
|
|||||||
std::string ToString() const;
|
std::string ToString() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AndroidNetworkMonitor : public rtc::NetworkMonitorInterface,
|
class AndroidNetworkMonitor : public rtc::NetworkMonitorInterface {
|
||||||
public rtc::NetworkBinderInterface {
|
|
||||||
public:
|
public:
|
||||||
AndroidNetworkMonitor(JNIEnv* env,
|
AndroidNetworkMonitor(JNIEnv* env,
|
||||||
const JavaRef<jobject>& j_application_context);
|
const JavaRef<jobject>& j_application_context);
|
||||||
@ -77,9 +76,14 @@ class AndroidNetworkMonitor : public rtc::NetworkMonitorInterface,
|
|||||||
void Start() override;
|
void Start() override;
|
||||||
void Stop() override;
|
void Stop() override;
|
||||||
|
|
||||||
|
// Does |this| NetworkMonitorInterface implement BindSocketToNetwork?
|
||||||
|
// Only Android returns true.
|
||||||
|
virtual bool SupportsBindSocketToNetwork() const override { return true; }
|
||||||
|
|
||||||
rtc::NetworkBindingResult BindSocketToNetwork(
|
rtc::NetworkBindingResult BindSocketToNetwork(
|
||||||
int socket_fd,
|
int socket_fd,
|
||||||
const rtc::IPAddress& address) override;
|
const rtc::IPAddress& address,
|
||||||
|
const std::string& if_name) override;
|
||||||
rtc::AdapterType GetAdapterType(const std::string& if_name) override;
|
rtc::AdapterType GetAdapterType(const std::string& if_name) override;
|
||||||
rtc::AdapterType GetVpnUnderlyingAdapterType(
|
rtc::AdapterType GetVpnUnderlyingAdapterType(
|
||||||
const std::string& if_name) override;
|
const std::string& if_name) override;
|
||||||
@ -106,8 +110,9 @@ class AndroidNetworkMonitor : public rtc::NetworkMonitorInterface,
|
|||||||
jint preference);
|
jint preference);
|
||||||
|
|
||||||
// Visible for testing.
|
// Visible for testing.
|
||||||
absl::optional<NetworkHandle> FindNetworkHandleFromAddress(
|
absl::optional<NetworkHandle> FindNetworkHandleFromAddressOrName(
|
||||||
const rtc::IPAddress& address) const;
|
const rtc::IPAddress& address,
|
||||||
|
const std::string& ifname) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OnNetworkConnected_n(const NetworkInformation& network_info);
|
void OnNetworkConnected_n(const NetworkInformation& network_info);
|
||||||
@ -115,6 +120,9 @@ class AndroidNetworkMonitor : public rtc::NetworkMonitorInterface,
|
|||||||
void OnNetworkPreference_n(NetworkType type,
|
void OnNetworkPreference_n(NetworkType type,
|
||||||
rtc::NetworkPreference preference);
|
rtc::NetworkPreference preference);
|
||||||
|
|
||||||
|
absl::optional<NetworkHandle> FindNetworkHandleFromIfname(
|
||||||
|
const std::string& ifname) const;
|
||||||
|
|
||||||
const int android_sdk_int_;
|
const int android_sdk_int_;
|
||||||
ScopedJavaGlobalRef<jobject> j_application_context_;
|
ScopedJavaGlobalRef<jobject> j_application_context_;
|
||||||
ScopedJavaGlobalRef<jobject> j_network_monitor_;
|
ScopedJavaGlobalRef<jobject> j_network_monitor_;
|
||||||
@ -133,6 +141,14 @@ class AndroidNetworkMonitor : public rtc::NetworkMonitorInterface,
|
|||||||
bool find_network_handle_without_ipv6_temporary_part_
|
bool find_network_handle_without_ipv6_temporary_part_
|
||||||
RTC_GUARDED_BY(network_thread_) = false;
|
RTC_GUARDED_BY(network_thread_) = false;
|
||||||
bool surface_cellular_types_ RTC_GUARDED_BY(network_thread_) = false;
|
bool surface_cellular_types_ RTC_GUARDED_BY(network_thread_) = false;
|
||||||
|
|
||||||
|
// NOTE: if bind_using_ifname_ is TRUE
|
||||||
|
// then the adapter name is used with substring matching as follows:
|
||||||
|
// An adapater name repored by android as 'wlan0'
|
||||||
|
// will be matched with 'v4-wlan0' ("v4-wlan0".find("wlan0") != npos).
|
||||||
|
// This applies to adapter_type_by_name_, vpn_underlying_adapter_type_by_name_
|
||||||
|
// and FindNetworkHandleFromIfname.
|
||||||
|
bool bind_using_ifname_ RTC_GUARDED_BY(network_thread_) = true;
|
||||||
const rtc::scoped_refptr<PendingTaskSafetyFlag> safety_flag_
|
const rtc::scoped_refptr<PendingTaskSafetyFlag> safety_flag_
|
||||||
RTC_PT_GUARDED_BY(network_thread_);
|
RTC_PT_GUARDED_BY(network_thread_);
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user