Add a field trial to use only the higher 64 bits to find network handle from an ipv6 address.
Bug: webrtc:11067 Change-Id: Ib4f069981f7641f67436757a8592ab0f168a9a6e Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/158800 Commit-Queue: Honghai Zhang <honghaiz@webrtc.org> Reviewed-by: Qingsi Wang <qingsi@webrtc.org> Reviewed-by: Alex Glaznev <glaznev@webrtc.org> Cr-Commit-Position: refs/heads/master@{#29697}
This commit is contained in:
committed by
Commit Bot
parent
7350a90237
commit
3c0e86a87d
@ -25,6 +25,7 @@
|
||||
#include "sdk/android/generated_base_jni/NetworkMonitor_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
#include "system_wrappers/include/field_trial.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
@ -135,6 +136,22 @@ static NetworkInformation GetNetworkInformationFromJava(
|
||||
return network_info;
|
||||
}
|
||||
|
||||
static bool AddressMatch(const rtc::IPAddress& ip1, const rtc::IPAddress& ip2) {
|
||||
if (ip1.family() != ip2.family()) {
|
||||
return false;
|
||||
}
|
||||
if (ip1.family() == AF_INET) {
|
||||
return ip1.ipv4_address().s_addr == ip2.ipv4_address().s_addr;
|
||||
}
|
||||
if (ip1.family() == AF_INET6) {
|
||||
// The last 64-bits of an ipv6 address are temporary address and it could
|
||||
// change over time. So we only compare the first 64-bits.
|
||||
return memcmp(ip1.ipv6_address().s6_addr, ip2.ipv6_address().s6_addr,
|
||||
sizeof(in6_addr) / 2) == 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
NetworkInformation::NetworkInformation() = default;
|
||||
|
||||
NetworkInformation::NetworkInformation(const NetworkInformation&) = default;
|
||||
@ -179,6 +196,9 @@ void AndroidNetworkMonitor::Start() {
|
||||
return;
|
||||
}
|
||||
started_ = true;
|
||||
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
|
||||
@ -196,6 +216,7 @@ void AndroidNetworkMonitor::Stop() {
|
||||
return;
|
||||
}
|
||||
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.
|
||||
@ -219,7 +240,8 @@ rtc::NetworkBindingResult AndroidNetworkMonitor::BindSocketToNetwork(
|
||||
RTC_CHECK(thread_checker_.IsCurrent());
|
||||
|
||||
// Android prior to Lollipop didn't have support for binding sockets to
|
||||
// networks. This may also occur if there is no connectivity manager service.
|
||||
// networks. This may also occur if there is no connectivity manager
|
||||
// service.
|
||||
JNIEnv* env = AttachCurrentThreadIfNeeded();
|
||||
const bool network_binding_supported =
|
||||
Java_NetworkMonitor_networkBindingSupported(env, j_network_monitor_);
|
||||
@ -230,13 +252,13 @@ rtc::NetworkBindingResult AndroidNetworkMonitor::BindSocketToNetwork(
|
||||
return rtc::NetworkBindingResult::NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
auto iter = network_handle_by_address_.find(address);
|
||||
if (iter == network_handle_by_address_.end()) {
|
||||
absl::optional<NetworkHandle> network_handle =
|
||||
FindNetworkHandleFromAddress(address);
|
||||
if (!network_handle) {
|
||||
return rtc::NetworkBindingResult::ADDRESS_NOT_FOUND;
|
||||
}
|
||||
NetworkHandle network_handle = iter->second;
|
||||
|
||||
if (network_handle == 0 /* NETWORK_UNSPECIFIED */) {
|
||||
if (*network_handle == 0 /* NETWORK_UNSPECIFIED */) {
|
||||
return rtc::NetworkBindingResult::NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
@ -267,10 +289,10 @@ rtc::NetworkBindingResult AndroidNetworkMonitor::BindSocketToNetwork(
|
||||
RTC_LOG(LS_ERROR) << "Symbol marshmallowSetNetworkForSocket is not found";
|
||||
return rtc::NetworkBindingResult::NOT_IMPLEMENTED;
|
||||
}
|
||||
rv = marshmallowSetNetworkForSocket(network_handle, socket_fd);
|
||||
rv = marshmallowSetNetworkForSocket(*network_handle, socket_fd);
|
||||
} else {
|
||||
// NOTE: This relies on Android implementation details, but it won't change
|
||||
// because Lollipop is already released.
|
||||
// NOTE: This relies on Android implementation details, but it won't
|
||||
// change because Lollipop is already released.
|
||||
typedef int (*LollipopSetNetworkForSocket)(unsigned net, int socket);
|
||||
static LollipopSetNetworkForSocket lollipopSetNetworkForSocket;
|
||||
// This is not threadsafe, but we are running this only on the worker
|
||||
@ -296,10 +318,10 @@ rtc::NetworkBindingResult AndroidNetworkMonitor::BindSocketToNetwork(
|
||||
RTC_LOG(LS_ERROR) << "Symbol lollipopSetNetworkForSocket is not found ";
|
||||
return rtc::NetworkBindingResult::NOT_IMPLEMENTED;
|
||||
}
|
||||
rv = lollipopSetNetworkForSocket(network_handle, socket_fd);
|
||||
rv = lollipopSetNetworkForSocket(*network_handle, socket_fd);
|
||||
}
|
||||
|
||||
// If |network| has since disconnected, |rv| will be ENONET. Surface this as
|
||||
// If |network| has since disconnected, |rv| will be ENONET. Surface this as
|
||||
// ERR_NETWORK_CHANGED, rather than MapSystemError(ENONET) which gives back
|
||||
// the less descriptive ERR_FAILED.
|
||||
if (rv == 0) {
|
||||
@ -335,6 +357,32 @@ void AndroidNetworkMonitor::OnNetworkConnected_w(
|
||||
}
|
||||
}
|
||||
|
||||
absl::optional<NetworkHandle>
|
||||
AndroidNetworkMonitor::FindNetworkHandleFromAddress(
|
||||
const rtc::IPAddress& ip_address) const {
|
||||
RTC_LOG(LS_INFO) << "Find network handle for address: "
|
||||
<< ip_address.ToString();
|
||||
if (find_network_handle_without_ipv6_temporary_part_) {
|
||||
for (auto const& iter : network_info_by_handle_) {
|
||||
const std::vector<rtc::IPAddress>& addresses = iter.second.ip_addresses;
|
||||
auto address_it = std::find_if(addresses.begin(), addresses.end(),
|
||||
[ip_address](rtc::IPAddress address) {
|
||||
return AddressMatch(ip_address, address);
|
||||
});
|
||||
if (address_it != addresses.end()) {
|
||||
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;
|
||||
}
|
||||
return absl::make_optional(iter->second);
|
||||
}
|
||||
}
|
||||
|
||||
void AndroidNetworkMonitor::OnNetworkDisconnected(NetworkHandle handle) {
|
||||
RTC_LOG(LS_INFO) << "Network disconnected for handle " << handle;
|
||||
worker_thread()->Invoke<void>(
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "rtc_base/network_monitor.h"
|
||||
#include "rtc_base/thread_checker.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
@ -61,8 +62,8 @@ struct NetworkInformation {
|
||||
class AndroidNetworkMonitor : public rtc::NetworkMonitorBase,
|
||||
public rtc::NetworkBinderInterface {
|
||||
public:
|
||||
explicit AndroidNetworkMonitor(JNIEnv* env,
|
||||
const JavaRef<jobject>& j_application_context);
|
||||
AndroidNetworkMonitor(JNIEnv* env,
|
||||
const JavaRef<jobject>& j_application_context);
|
||||
~AndroidNetworkMonitor() override;
|
||||
|
||||
// TODO(sakal): Remove once down stream dependencies have been updated.
|
||||
@ -94,6 +95,10 @@ class AndroidNetworkMonitor : public rtc::NetworkMonitorBase,
|
||||
const JavaRef<jobject>& j_caller,
|
||||
const JavaRef<jobjectArray>& j_network_infos);
|
||||
|
||||
// Visible for testing.
|
||||
absl::optional<NetworkHandle> FindNetworkHandleFromAddress(
|
||||
const rtc::IPAddress& address) const;
|
||||
|
||||
private:
|
||||
void OnNetworkConnected_w(const NetworkInformation& network_info);
|
||||
void OnNetworkDisconnected_w(NetworkHandle network_handle);
|
||||
@ -107,6 +112,7 @@ class AndroidNetworkMonitor : public rtc::NetworkMonitorBase,
|
||||
std::map<std::string, rtc::AdapterType> vpn_underlying_adapter_type_by_name_;
|
||||
std::map<rtc::IPAddress, NetworkHandle> network_handle_by_address_;
|
||||
std::map<NetworkHandle, NetworkInformation> network_info_by_handle_;
|
||||
bool find_network_handle_without_ipv6_temporary_part_;
|
||||
};
|
||||
|
||||
class AndroidNetworkMonitorFactory : public rtc::NetworkMonitorFactory {
|
||||
|
||||
Reference in New Issue
Block a user