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}
This commit is contained in:
committed by
Commit Bot
parent
89cb65ed66
commit
da2fd2a2b2
@ -212,7 +212,8 @@ AdapterType GetAdapterTypeFromName(const char* network_name) {
|
||||
return ADAPTER_TYPE_ETHERNET;
|
||||
}
|
||||
|
||||
if (MatchTypeNameWithIndexPattern(network_name, "wlan")) {
|
||||
if (MatchTypeNameWithIndexPattern(network_name, "wlan") ||
|
||||
MatchTypeNameWithIndexPattern(network_name, "v4-wlan")) {
|
||||
return ADAPTER_TYPE_WIFI;
|
||||
}
|
||||
|
||||
@ -478,15 +479,15 @@ Network* NetworkManagerBase::GetNetworkFromAddress(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BasicNetworkManager::BasicNetworkManager()
|
||||
: allow_mac_based_ipv6_(
|
||||
webrtc::field_trial::IsEnabled("WebRTC-AllowMACBasedIPv6")) {}
|
||||
BasicNetworkManager::BasicNetworkManager() : BasicNetworkManager(nullptr) {}
|
||||
|
||||
BasicNetworkManager::BasicNetworkManager(
|
||||
NetworkMonitorFactory* network_monitor_factory)
|
||||
: network_monitor_factory_(network_monitor_factory),
|
||||
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() {}
|
||||
|
||||
@ -865,6 +866,15 @@ void BasicNetworkManager::StartNetworkMonitor() {
|
||||
network_monitor_->SignalNetworksChanged.connect(
|
||||
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();
|
||||
}
|
||||
|
||||
@ -873,6 +883,13 @@ void BasicNetworkManager::StopNetworkMonitor() {
|
||||
return;
|
||||
}
|
||||
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) {
|
||||
@ -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,
|
||||
const std::string& desc,
|
||||
const IPAddress& prefix,
|
||||
|
||||
@ -194,11 +194,11 @@ class RTC_EXPORT NetworkManagerBase : public NetworkManager {
|
||||
void set_default_local_addresses(const IPAddress& ipv4,
|
||||
const IPAddress& ipv6);
|
||||
|
||||
Network* GetNetworkFromAddress(const rtc::IPAddress& ip) const;
|
||||
|
||||
private:
|
||||
friend class NetworkTest;
|
||||
|
||||
Network* GetNetworkFromAddress(const rtc::IPAddress& ip) const;
|
||||
|
||||
EnumerationPermission enumeration_permission_;
|
||||
|
||||
NetworkList networks_;
|
||||
@ -225,6 +225,7 @@ class RTC_EXPORT NetworkManagerBase : public NetworkManager {
|
||||
// of networks using OS APIs.
|
||||
class RTC_EXPORT BasicNetworkManager : public NetworkManagerBase,
|
||||
public MessageHandlerAutoCleanup,
|
||||
public NetworkBinderInterface,
|
||||
public sigslot::has_slots<> {
|
||||
public:
|
||||
BasicNetworkManager();
|
||||
@ -248,6 +249,15 @@ class RTC_EXPORT BasicNetworkManager : public NetworkManagerBase,
|
||||
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:
|
||||
#if defined(WEBRTC_POSIX)
|
||||
// Separated from CreateNetworks for tests.
|
||||
@ -293,7 +303,8 @@ class RTC_EXPORT BasicNetworkManager : public NetworkManagerBase,
|
||||
nullptr;
|
||||
std::unique_ptr<NetworkMonitorInterface> network_monitor_
|
||||
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.
|
||||
|
||||
@ -36,6 +36,8 @@ enum class NetworkPreference {
|
||||
|
||||
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 {
|
||||
public:
|
||||
// Binds a socket to the network that is attached to |address| so that all
|
||||
@ -83,6 +85,19 @@ class NetworkMonitorInterface {
|
||||
virtual NetworkPreference GetNetworkPreference(
|
||||
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
|
||||
// this returns false.
|
||||
//
|
||||
|
||||
@ -76,9 +76,35 @@ class FakeNetworkMonitor : public NetworkMonitorInterface {
|
||||
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:
|
||||
bool started_ = false;
|
||||
std::vector<std::string> adapters_;
|
||||
std::vector<std::string> unavailable_adapters_;
|
||||
std::vector<IPAddress> addresses_;
|
||||
};
|
||||
|
||||
class FakeNetworkMonitorFactory : public NetworkMonitorFactory {
|
||||
@ -1279,4 +1305,48 @@ TEST_F(NetworkTest, WebRTC_AllowMACBasedIPv6Address) {
|
||||
}
|
||||
#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
|
||||
|
||||
@ -69,7 +69,7 @@ TEST_F(AndroidNetworkMonitorTest, TestFindNetworkHandleUsingIpv4Address) {
|
||||
network_monitor_->SetNetworkInfos(net_infos);
|
||||
|
||||
auto network_handle =
|
||||
network_monitor_->FindNetworkHandleFromAddress(ipv4_address);
|
||||
network_monitor_->FindNetworkHandleFromAddressOrName(ipv4_address, "");
|
||||
|
||||
ASSERT_TRUE(network_handle.has_value());
|
||||
EXPECT_EQ(ipv4_handle, *network_handle);
|
||||
@ -86,9 +86,9 @@ TEST_F(AndroidNetworkMonitorTest, TestFindNetworkHandleUsingFullIpv6Address) {
|
||||
network_monitor_->SetNetworkInfos(net_infos);
|
||||
|
||||
auto network_handle1 =
|
||||
network_monitor_->FindNetworkHandleFromAddress(ipv6_address1);
|
||||
network_monitor_->FindNetworkHandleFromAddressOrName(ipv6_address1, "");
|
||||
auto network_handle2 =
|
||||
network_monitor_->FindNetworkHandleFromAddress(ipv6_address2);
|
||||
network_monitor_->FindNetworkHandleFromAddressOrName(ipv6_address2, "");
|
||||
|
||||
ASSERT_TRUE(network_handle1.has_value());
|
||||
EXPECT_EQ(ipv6_handle, *network_handle1);
|
||||
@ -111,9 +111,9 @@ TEST_F(AndroidNetworkMonitorTest,
|
||||
network_monitor_->SetNetworkInfos(net_infos);
|
||||
|
||||
auto network_handle1 =
|
||||
network_monitor_->FindNetworkHandleFromAddress(ipv6_address1);
|
||||
network_monitor_->FindNetworkHandleFromAddressOrName(ipv6_address1, "");
|
||||
auto network_handle2 =
|
||||
network_monitor_->FindNetworkHandleFromAddress(ipv6_address2);
|
||||
network_monitor_->FindNetworkHandleFromAddressOrName(ipv6_address2, "");
|
||||
|
||||
ASSERT_TRUE(network_handle1.has_value());
|
||||
EXPECT_EQ(ipv6_handle, *network_handle1);
|
||||
@ -121,5 +121,33 @@ TEST_F(AndroidNetworkMonitorTest,
|
||||
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);
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
@ -243,11 +243,8 @@ void AndroidNetworkMonitor::Start() {
|
||||
find_network_handle_without_ipv6_temporary_part_ =
|
||||
webrtc::field_trial::IsEnabled(
|
||||
"WebRTC-FindNetworkHandleWithoutIpv6TemporaryPart");
|
||||
|
||||
// This is kind of magic behavior, but doing this allows the SocketServer to
|
||||
// use this as a NetworkBinder to bind sockets on a particular network when
|
||||
// it creates sockets.
|
||||
network_thread_->socketserver()->set_network_binder(this);
|
||||
bind_using_ifname_ =
|
||||
webrtc::field_trial::IsEnabled("WebRTC-BindUsingInterfaceName");
|
||||
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
Java_NetworkMonitor_startMonitoring(
|
||||
@ -262,12 +259,6 @@ void AndroidNetworkMonitor::Stop() {
|
||||
started_ = false;
|
||||
find_network_handle_without_ipv6_temporary_part_ = false;
|
||||
|
||||
// Once the network monitor stops, it will clear all network information and
|
||||
// it won't find the network handle to bind anyway.
|
||||
if (network_thread_->socketserver()->network_binder() == this) {
|
||||
network_thread_->socketserver()->set_network_binder(nullptr);
|
||||
}
|
||||
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
Java_NetworkMonitor_stopMonitoring(env, j_network_monitor_,
|
||||
jlongFromPointer(this));
|
||||
@ -280,7 +271,8 @@ void AndroidNetworkMonitor::Stop() {
|
||||
// https://cs.chromium.org/chromium/src/net/udp/udp_socket_posix.cc
|
||||
rtc::NetworkBindingResult AndroidNetworkMonitor::BindSocketToNetwork(
|
||||
int socket_fd,
|
||||
const rtc::IPAddress& address) {
|
||||
const rtc::IPAddress& address,
|
||||
const std::string& if_name) {
|
||||
RTC_DCHECK_RUN_ON(network_thread_);
|
||||
|
||||
// Android prior to Lollipop didn't have support for binding sockets to
|
||||
@ -298,12 +290,18 @@ rtc::NetworkBindingResult AndroidNetworkMonitor::BindSocketToNetwork(
|
||||
}
|
||||
|
||||
absl::optional<NetworkHandle> network_handle =
|
||||
FindNetworkHandleFromAddress(address);
|
||||
FindNetworkHandleFromAddressOrName(address, if_name);
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -370,11 +368,19 @@ rtc::NetworkBindingResult AndroidNetworkMonitor::BindSocketToNetwork(
|
||||
// ERR_NETWORK_CHANGED, rather than MapSystemError(ENONET) which gives back
|
||||
// the less descriptive ERR_FAILED.
|
||||
if (rv == 0) {
|
||||
RTC_LOG(LS_VERBOSE) << "BindSocketToNetwork bound network handle for"
|
||||
<< " addr: " << address.ToSensitiveString()
|
||||
<< " ifname: " << if_name;
|
||||
return rtc::NetworkBindingResult::SUCCESS;
|
||||
}
|
||||
|
||||
RTC_LOG(LS_WARNING) << "BindSocketToNetwork got error: " << rv
|
||||
<< " addr: " << address.ToSensitiveString()
|
||||
<< " ifname: " << if_name;
|
||||
if (rv == ENONET) {
|
||||
return rtc::NetworkBindingResult::NETWORK_CHANGED;
|
||||
}
|
||||
|
||||
return rtc::NetworkBindingResult::FAILURE;
|
||||
}
|
||||
|
||||
@ -397,8 +403,9 @@ void AndroidNetworkMonitor::OnNetworkConnected_n(
|
||||
}
|
||||
|
||||
absl::optional<NetworkHandle>
|
||||
AndroidNetworkMonitor::FindNetworkHandleFromAddress(
|
||||
const rtc::IPAddress& ip_address) const {
|
||||
AndroidNetworkMonitor::FindNetworkHandleFromAddressOrName(
|
||||
const rtc::IPAddress& ip_address,
|
||||
const std::string& if_name) const {
|
||||
RTC_DCHECK_RUN_ON(network_thread_);
|
||||
RTC_LOG(LS_INFO) << "Find network handle.";
|
||||
if (find_network_handle_without_ipv6_temporary_part_) {
|
||||
@ -412,14 +419,29 @@ AndroidNetworkMonitor::FindNetworkHandleFromAddress(
|
||||
return absl::make_optional(iter.first);
|
||||
}
|
||||
}
|
||||
return absl::nullopt;
|
||||
} else {
|
||||
auto iter = network_handle_by_address_.find(ip_address);
|
||||
if (iter == network_handle_by_address_.end()) {
|
||||
return absl::nullopt;
|
||||
if (iter != network_handle_by_address_.end()) {
|
||||
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) {
|
||||
return absl::make_optional(iter.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
void AndroidNetworkMonitor::OnNetworkDisconnected_n(NetworkHandle handle) {
|
||||
@ -465,6 +487,16 @@ rtc::AdapterType AndroidNetworkMonitor::GetAdapterType(
|
||||
rtc::AdapterType type = (iter == adapter_type_by_name_.end())
|
||||
? rtc::ADAPTER_TYPE_UNKNOWN
|
||||
: iter->second;
|
||||
|
||||
if (type == rtc::ADAPTER_TYPE_UNKNOWN && bind_using_ifname_) {
|
||||
for (auto const& iter : adapter_type_by_name_) {
|
||||
if (if_name.find(iter.first) != std::string::npos) {
|
||||
type = iter.second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type == rtc::ADAPTER_TYPE_UNKNOWN) {
|
||||
RTC_LOG(LS_WARNING) << "Get an unknown type for the interface " << if_name;
|
||||
}
|
||||
@ -478,6 +510,15 @@ rtc::AdapterType AndroidNetworkMonitor::GetVpnUnderlyingAdapterType(
|
||||
rtc::AdapterType type = (iter == vpn_underlying_adapter_type_by_name_.end())
|
||||
? rtc::ADAPTER_TYPE_UNKNOWN
|
||||
: iter->second;
|
||||
if (type == rtc::ADAPTER_TYPE_UNKNOWN && bind_using_ifname_) {
|
||||
for (auto const& iter : adapter_type_by_name_) {
|
||||
if (if_name.find(iter.first) != std::string::npos) {
|
||||
type = iter.second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
@ -62,8 +62,7 @@ struct NetworkInformation {
|
||||
std::string ToString() const;
|
||||
};
|
||||
|
||||
class AndroidNetworkMonitor : public rtc::NetworkMonitorInterface,
|
||||
public rtc::NetworkBinderInterface {
|
||||
class AndroidNetworkMonitor : public rtc::NetworkMonitorInterface {
|
||||
public:
|
||||
AndroidNetworkMonitor(JNIEnv* env,
|
||||
const JavaRef<jobject>& j_application_context);
|
||||
@ -75,9 +74,14 @@ class AndroidNetworkMonitor : public rtc::NetworkMonitorInterface,
|
||||
void Start() override;
|
||||
void Stop() override;
|
||||
|
||||
// Does |this| NetworkMonitorInterface implement BindSocketToNetwork?
|
||||
// Only Android returns true.
|
||||
virtual bool SupportsBindSocketToNetwork() const override { return true; }
|
||||
|
||||
rtc::NetworkBindingResult BindSocketToNetwork(
|
||||
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 GetVpnUnderlyingAdapterType(
|
||||
const std::string& if_name) override;
|
||||
@ -104,8 +108,9 @@ class AndroidNetworkMonitor : public rtc::NetworkMonitorInterface,
|
||||
jint preference);
|
||||
|
||||
// Visible for testing.
|
||||
absl::optional<NetworkHandle> FindNetworkHandleFromAddress(
|
||||
const rtc::IPAddress& address) const;
|
||||
absl::optional<NetworkHandle> FindNetworkHandleFromAddressOrName(
|
||||
const rtc::IPAddress& address,
|
||||
const std::string& ifname) const;
|
||||
|
||||
private:
|
||||
void OnNetworkConnected_n(const NetworkInformation& network_info);
|
||||
@ -113,6 +118,9 @@ class AndroidNetworkMonitor : public rtc::NetworkMonitorInterface,
|
||||
void OnNetworkPreference_n(NetworkType type,
|
||||
rtc::NetworkPreference preference);
|
||||
|
||||
absl::optional<NetworkHandle> FindNetworkHandleFromIfname(
|
||||
const std::string& ifname) const;
|
||||
|
||||
const int android_sdk_int_;
|
||||
ScopedJavaGlobalRef<jobject> j_application_context_;
|
||||
ScopedJavaGlobalRef<jobject> j_network_monitor_;
|
||||
@ -131,6 +139,7 @@ class AndroidNetworkMonitor : public rtc::NetworkMonitorInterface,
|
||||
bool find_network_handle_without_ipv6_temporary_part_
|
||||
RTC_GUARDED_BY(network_thread_) = false;
|
||||
bool surface_cellular_types_ RTC_GUARDED_BY(network_thread_) = false;
|
||||
bool bind_using_ifname_ RTC_GUARDED_BY(network_thread_) = true;
|
||||
};
|
||||
|
||||
class AndroidNetworkMonitorFactory : public rtc::NetworkMonitorFactory {
|
||||
|
||||
Reference in New Issue
Block a user