Implement network monitor for iOS.

Notably, this should detect whether an interface is "available" or not,
which should prevent the failure is with dual SIM card setups.

This is gated behind a field trial for now, to ensure this doesn't cause
any regressions due to false negatives (interfaces that are usable
but not listed as available by NWPathMonitor).

Bug: webrtc:10966
Change-Id: Ia3942c4c57b525d08d8b340e2325f3705cfd0304
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/180923
Commit-Queue: Taylor <deadbeef@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Jonas Oreland <jonaso@webrtc.org>
Reviewed-by: Anders Carlsson <andersc@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31977}
This commit is contained in:
Taylor Brandstetter
2020-08-19 16:41:54 -07:00
committed by Commit Bot
parent bedb605c82
commit ea7fbfb966
17 changed files with 549 additions and 0 deletions

View File

@ -0,0 +1,39 @@
/*
* Copyright 2020 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef SDK_OBJC_NATIVE_SRC_NETWORK_MONITOR_OBSERVER_H_
#define SDK_OBJC_NATIVE_SRC_NETWORK_MONITOR_OBSERVER_H_
#include <map>
#include <string>
#include "rtc_base/network_constants.h"
#include "rtc_base/thread.h"
namespace webrtc {
// Observer interface for listening to NWPathMonitor updates.
class NetworkMonitorObserver {
public:
// Called when a path update occurs, on network monitor dispatch queue.
//
// |adapter_type_by_name| is a map from interface name (i.e. "pdp_ip0") to
// adapter type, for all available interfaces on the current path. If an
// interface name isn't present it can be assumed to be unavailable.
virtual void OnPathUpdate(
std::map<std::string, rtc::AdapterType> adapter_type_by_name) = 0;
protected:
virtual ~NetworkMonitorObserver() {}
};
} // namespace webrtc
#endif // SDK_OBJC_NATIVE_SRC_AUDIO_AUDIO_SESSION_OBSERVER_H_

View File

@ -0,0 +1,72 @@
/*
* Copyright 2020 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef SDK_OBJC_NATIVE_SRC_OBJC_NETWORK_MONITOR_H_
#define SDK_OBJC_NATIVE_SRC_OBJC_NETWORK_MONITOR_H_
#include <vector>
#include "sdk/objc/components/network/RTCNetworkMonitor+Private.h"
#include "sdk/objc/native/src/network_monitor_observer.h"
#include "rtc_base/async_invoker.h"
#include "rtc_base/network_monitor.h"
#include "rtc_base/network_monitor_factory.h"
#include "rtc_base/synchronization/sequence_checker.h"
#include "rtc_base/thread.h"
#include "rtc_base/thread_annotations.h"
namespace webrtc {
class ObjCNetworkMonitorFactory : public rtc::NetworkMonitorFactory {
public:
ObjCNetworkMonitorFactory() = default;
~ObjCNetworkMonitorFactory() override = default;
rtc::NetworkMonitorInterface* CreateNetworkMonitor() override;
};
class ObjCNetworkMonitor : public rtc::NetworkMonitorInterface,
public NetworkMonitorObserver {
public:
ObjCNetworkMonitor() = default;
~ObjCNetworkMonitor() override;
void Start() override;
void Stop() override;
// TODO(deadbeef): Remove this once it's been removed from
// NetworkMonitorInterface.
void OnNetworksChanged() override {}
rtc::AdapterType GetAdapterType(const std::string& interface_name) override;
rtc::AdapterType GetVpnUnderlyingAdapterType(
const std::string& interface_name) override;
rtc::NetworkPreference GetNetworkPreference(
const std::string& interface_name) override;
bool IsAdapterAvailable(const std::string& interface_name) override;
// NetworkMonitorObserver override.
// Fans out updates to observers on the correct thread.
void OnPathUpdate(
std::map<std::string, rtc::AdapterType> adapter_type_by_name) override;
private:
rtc::Thread* thread_ = nullptr;
bool started_ = false;
std::map<std::string, rtc::AdapterType> adapter_type_by_name_
RTC_GUARDED_BY(thread_);
rtc::AsyncInvoker invoker_;
RTCNetworkMonitor* network_monitor_ = nil;
};
} // namespace webrtc
#endif // SDK_OBJC_NATIVE_SRC_OBJC_NETWORK_MONITOR_H_

View File

@ -0,0 +1,86 @@
/*
* Copyright 2020 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "sdk/objc/native/src/objc_network_monitor.h"
#include <algorithm>
#include "rtc_base/logging.h"
namespace webrtc {
rtc::NetworkMonitorInterface* ObjCNetworkMonitorFactory::CreateNetworkMonitor() {
return new ObjCNetworkMonitor();
}
ObjCNetworkMonitor::~ObjCNetworkMonitor() {
network_monitor_ = nil;
}
void ObjCNetworkMonitor::Start() {
if (started_) {
return;
}
thread_ = rtc::Thread::Current();
RTC_DCHECK_RUN_ON(thread_);
network_monitor_ = [[RTCNetworkMonitor alloc] initWithObserver:this];
if (network_monitor_ == nil) {
RTC_LOG(LS_WARNING) << "Failed to create RTCNetworkMonitor; not available on this OS?";
}
started_ = true;
}
void ObjCNetworkMonitor::Stop() {
RTC_DCHECK_RUN_ON(thread_);
if (!started_) {
return;
}
network_monitor_ = nil;
started_ = false;
}
rtc::AdapterType ObjCNetworkMonitor::GetAdapterType(const std::string& interface_name) {
RTC_DCHECK_RUN_ON(thread_);
if (adapter_type_by_name_.find(interface_name) == adapter_type_by_name_.end()) {
return rtc::ADAPTER_TYPE_UNKNOWN;
}
return adapter_type_by_name_.at(interface_name);
}
rtc::AdapterType ObjCNetworkMonitor::GetVpnUnderlyingAdapterType(
const std::string& interface_name) {
return rtc::ADAPTER_TYPE_UNKNOWN;
}
rtc::NetworkPreference ObjCNetworkMonitor::GetNetworkPreference(const std::string& interface_name) {
return rtc::NetworkPreference::NEUTRAL;
}
bool ObjCNetworkMonitor::IsAdapterAvailable(const std::string& interface_name) {
RTC_DCHECK_RUN_ON(thread_);
if (adapter_type_by_name_.empty()) {
// If we have no path update, assume everything's available, because it's
// preferable for WebRTC to try all interfaces rather than none at all.
return true;
}
return adapter_type_by_name_.find(interface_name) != adapter_type_by_name_.end();
}
void ObjCNetworkMonitor::OnPathUpdate(
std::map<std::string, rtc::AdapterType> adapter_type_by_name) {
RTC_DCHECK(network_monitor_ != nil);
invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, adapter_type_by_name] {
RTC_DCHECK_RUN_ON(thread_);
adapter_type_by_name_ = adapter_type_by_name;
SignalNetworksChanged();
});
}
} // namespace webrtc