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:

committed by
Commit Bot

parent
bedb605c82
commit
ea7fbfb966
@ -806,6 +806,11 @@ bool BasicNetworkManager::IsIgnoredNetwork(const Network& network) const {
|
||||
}
|
||||
#endif
|
||||
|
||||
if (network_monitor_ &&
|
||||
!network_monitor_->IsAdapterAvailable(network.name())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ignore any networks with a 0.x.y.z IP
|
||||
if (network.prefix().family() == AF_INET) {
|
||||
return (network.prefix().v4AddressAsHostOrderInteger() < 0x01000000);
|
||||
|
@ -77,15 +77,34 @@ class NetworkMonitorInterface {
|
||||
|
||||
// Implementations should call this method on the base when networks change,
|
||||
// and the base will fire SignalNetworksChanged on the right thread.
|
||||
// TODO(deadbeef): This is an implementation detail of NetworkMonitorBase,
|
||||
// it doesn't belong here.
|
||||
virtual void OnNetworksChanged() = 0;
|
||||
|
||||
virtual AdapterType GetAdapterType(const std::string& interface_name) = 0;
|
||||
virtual AdapterType GetVpnUnderlyingAdapterType(
|
||||
const std::string& interface_name) = 0;
|
||||
|
||||
virtual NetworkPreference GetNetworkPreference(
|
||||
const std::string& interface_name) = 0;
|
||||
|
||||
// Is this interface available to use? WebRTC shouldn't attempt to use it if
|
||||
// this returns false.
|
||||
//
|
||||
// It's possible for this status to change, in which case
|
||||
// SignalNetworksChanged will be fired.
|
||||
//
|
||||
// These specific use case this was added for was a phone with two SIM cards,
|
||||
// where attempting to use all interfaces returned from getifaddrs caused the
|
||||
// connection to be dropped.
|
||||
virtual bool IsAdapterAvailable(const std::string& interface_name) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO(deadbeef): This class has marginal value, all it does is post a task
|
||||
// to call SignalNetworksChanged on the worker thread. Should fold it into
|
||||
// AndroidNetworkMonitor.
|
||||
class NetworkMonitorBase : public NetworkMonitorInterface,
|
||||
public MessageHandler,
|
||||
public sigslot::has_slots<> {
|
||||
|
@ -12,9 +12,11 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/algorithm/container.h"
|
||||
#include "absl/strings/match.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/net_helpers.h"
|
||||
@ -61,8 +63,18 @@ class FakeNetworkMonitor : public NetworkMonitorBase {
|
||||
return NetworkPreference::NEUTRAL;
|
||||
}
|
||||
|
||||
bool IsAdapterAvailable(const std::string& if_name) override {
|
||||
return absl::c_count(unavailable_adapters_, if_name) == 0;
|
||||
}
|
||||
|
||||
// Used to test IsAdapterAvailable.
|
||||
void set_unavailable_adapters(std::vector<std::string> unavailable_adapters) {
|
||||
unavailable_adapters_ = unavailable_adapters;
|
||||
}
|
||||
|
||||
private:
|
||||
bool started_ = false;
|
||||
std::vector<std::string> unavailable_adapters_;
|
||||
};
|
||||
|
||||
class FakeNetworkMonitorFactory : public NetworkMonitorFactory {
|
||||
@ -914,6 +926,41 @@ TEST_F(NetworkTest, TestGetAdapterTypeFromNameMatching) {
|
||||
ReleaseIfAddrs(addr_list);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Test that an adapter won't be included in the network list if there's a
|
||||
// network monitor that says it's unavailable.
|
||||
TEST_F(NetworkTest, TestNetworkMonitorIsAdapterAvailable) {
|
||||
char if_name1[20] = "pdp_ip0";
|
||||
char if_name2[20] = "pdp_ip1";
|
||||
ifaddrs* list = nullptr;
|
||||
list = AddIpv6Address(list, if_name1, "1000:2000:3000:4000:0:0:0:1",
|
||||
"FFFF:FFFF:FFFF:FFFF::", 0);
|
||||
list = AddIpv6Address(list, if_name2, "1000:2000:3000:4000:0:0:0:2",
|
||||
"FFFF:FFFF:FFFF:FFFF::", 0);
|
||||
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());
|
||||
bool changed;
|
||||
// This ensures we release the objects created in CallConvertIfAddrs.
|
||||
MergeNetworkList(manager, result, &changed);
|
||||
result.clear();
|
||||
|
||||
// Now simulate one interface being unavailable.
|
||||
FakeNetworkMonitor* network_monitor = GetNetworkMonitor(manager);
|
||||
network_monitor->set_unavailable_adapters({if_name1});
|
||||
CallConvertIfAddrs(manager, list, /*include_ignored=*/false, &result);
|
||||
EXPECT_EQ(1u, result.size());
|
||||
EXPECT_EQ(if_name2, result[0]->name());
|
||||
|
||||
MergeNetworkList(manager, result, &changed);
|
||||
ReleaseIfAddrs(list);
|
||||
}
|
||||
|
||||
#endif // defined(WEBRTC_POSIX)
|
||||
|
||||
// Test MergeNetworkList successfully combines all IPs for the same
|
||||
|
53
sdk/BUILD.gn
53
sdk/BUILD.gn
@ -337,6 +337,35 @@ if (is_ios || is_mac) {
|
||||
"../rtc_base:rtc_base_approved",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_source_set("network_monitor_observer") {
|
||||
visibility = [ ":*" ]
|
||||
|
||||
sources = [ "objc/native/src/network_monitor_observer.h" ]
|
||||
|
||||
deps = [ "../rtc_base" ]
|
||||
}
|
||||
|
||||
rtc_library("network_monitor_objc") {
|
||||
visibility = [ "*" ]
|
||||
|
||||
sources = [
|
||||
"objc/components/network/RTCNetworkMonitor+Private.h",
|
||||
"objc/components/network/RTCNetworkMonitor.h",
|
||||
"objc/components/network/RTCNetworkMonitor.mm",
|
||||
]
|
||||
|
||||
configs += [ ":used_from_extension" ]
|
||||
|
||||
frameworks = [ "Network.framework" ]
|
||||
|
||||
deps = [
|
||||
":base_objc",
|
||||
":helpers_objc",
|
||||
":network_monitor_observer",
|
||||
"../rtc_base/system:gcd_helpers",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
rtc_library("videosource_objc") {
|
||||
@ -1266,6 +1295,7 @@ if (is_ios || is_mac) {
|
||||
"objc/components/audio/RTCAudioSessionConfiguration.h",
|
||||
"objc/components/capturer/RTCCameraVideoCapturer.h",
|
||||
"objc/components/capturer/RTCFileVideoCapturer.h",
|
||||
"objc/components/network/RTCNetworkMonitor.h",
|
||||
"objc/components/renderer/metal/RTCMTLVideoView.h",
|
||||
"objc/components/renderer/opengl/RTCEAGLVideoView.h",
|
||||
"objc/components/renderer/opengl/RTCVideoViewShading.h",
|
||||
@ -1540,6 +1570,8 @@ if (is_ios || is_mac) {
|
||||
visibility = [ "*" ]
|
||||
allow_poison = [ "audio_codecs" ] # TODO(bugs.webrtc.org/8396): Remove.
|
||||
sources = [
|
||||
"objc/native/api/network_monitor_factory.h",
|
||||
"objc/native/api/network_monitor_factory.mm",
|
||||
"objc/native/api/video_capturer.h",
|
||||
"objc/native/api/video_capturer.mm",
|
||||
"objc/native/api/video_decoder_factory.h",
|
||||
@ -1571,9 +1603,30 @@ if (is_ios || is_mac) {
|
||||
"../common_video",
|
||||
"../rtc_base",
|
||||
]
|
||||
if (is_ios) {
|
||||
deps += [ ":native_network_monitor" ]
|
||||
}
|
||||
absl_deps = [ "//third_party/abseil-cpp/absl/memory" ]
|
||||
}
|
||||
|
||||
if (is_ios) {
|
||||
rtc_library("native_network_monitor") {
|
||||
visibility = [ "*" ]
|
||||
|
||||
sources = [
|
||||
"objc/native/src/objc_network_monitor.h",
|
||||
"objc/native/src/objc_network_monitor.mm",
|
||||
]
|
||||
|
||||
deps = [
|
||||
":network_monitor_objc",
|
||||
":network_monitor_observer",
|
||||
"../rtc_base",
|
||||
"../rtc_base/synchronization:sequence_checker",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
rtc_library("native_video") {
|
||||
sources = [
|
||||
"objc/native/src/objc_frame_buffer.h",
|
||||
|
@ -21,6 +21,7 @@ RTC_EXTERN NSString * const kRTCFieldTrialFlexFec03AdvertisedKey;
|
||||
RTC_EXTERN NSString * const kRTCFieldTrialFlexFec03Key;
|
||||
RTC_EXTERN NSString * const kRTCFieldTrialH264HighProfileKey;
|
||||
RTC_EXTERN NSString * const kRTCFieldTrialMinimizeResamplingOnMobileKey;
|
||||
RTC_EXTERN NSString *const kRTCFieldTrialUseNWPathMonitor;
|
||||
|
||||
/** The valid value for field trials above. */
|
||||
RTC_EXTERN NSString * const kRTCFieldTrialEnabledValue;
|
||||
|
@ -25,6 +25,7 @@ NSString * const kRTCFieldTrialFlexFec03Key = @"WebRTC-FlexFEC-03";
|
||||
NSString * const kRTCFieldTrialH264HighProfileKey = @"WebRTC-H264HighProfile";
|
||||
NSString * const kRTCFieldTrialMinimizeResamplingOnMobileKey =
|
||||
@"WebRTC-Audio-MinimizeResamplingOnMobile";
|
||||
NSString *const kRTCFieldTrialUseNWPathMonitor = @"WebRTC-Network-UseNWPathMonitor";
|
||||
NSString * const kRTCFieldTrialEnabledValue = @"Enabled";
|
||||
|
||||
static std::unique_ptr<char[]> gFieldTrialInitString;
|
||||
|
@ -25,6 +25,9 @@
|
||||
#import "base/RTCVideoDecoderFactory.h"
|
||||
#import "base/RTCVideoEncoderFactory.h"
|
||||
#import "helpers/NSString+StdString.h"
|
||||
#include "sdk/objc/native/api/network_monitor_factory.h"
|
||||
#include "system_wrappers/include/field_trial.h"
|
||||
|
||||
#ifndef HAVE_NO_MEDIA
|
||||
#import "components/video_codec/RTCVideoDecoderFactoryH264.h"
|
||||
#import "components/video_codec/RTCVideoEncoderFactoryH264.h"
|
||||
@ -135,6 +138,9 @@
|
||||
dependencies.network_thread = _networkThread.get();
|
||||
dependencies.worker_thread = _workerThread.get();
|
||||
dependencies.signaling_thread = _signalingThread.get();
|
||||
if (webrtc::field_trial::IsEnabled("WebRTC-Network-UseNWPathMonitor")) {
|
||||
dependencies.network_monitor_factory = webrtc::CreateNetworkMonitorFactory();
|
||||
}
|
||||
_nativeFactory = webrtc::CreateModularPeerConnectionFactory(std::move(dependencies));
|
||||
NSAssert(_nativeFactory, @"Failed to initialize PeerConnectionFactory!");
|
||||
}
|
||||
@ -179,6 +185,9 @@
|
||||
dependencies.network_thread = _networkThread.get();
|
||||
dependencies.worker_thread = _workerThread.get();
|
||||
dependencies.signaling_thread = _signalingThread.get();
|
||||
if (webrtc::field_trial::IsEnabled("WebRTC-Network-UseNWPathMonitor")) {
|
||||
dependencies.network_monitor_factory = webrtc::CreateNetworkMonitorFactory();
|
||||
}
|
||||
#ifndef HAVE_NO_MEDIA
|
||||
dependencies.task_queue_factory = webrtc::CreateDefaultTaskQueueFactory();
|
||||
cricket::MediaEngineDependencies media_deps;
|
||||
|
23
sdk/objc/components/network/RTCNetworkMonitor+Private.h
Normal file
23
sdk/objc/components/network/RTCNetworkMonitor+Private.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import "RTCNetworkMonitor.h"
|
||||
|
||||
#include "sdk/objc/native/src/network_monitor_observer.h"
|
||||
|
||||
@interface RTCNetworkMonitor ()
|
||||
|
||||
/** |observer| is a raw pointer and should be kept alive
|
||||
* for this object's lifetime.
|
||||
*/
|
||||
- (instancetype)initWithObserver:(webrtc::NetworkMonitorObserver *)observer
|
||||
NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@end
|
24
sdk/objc/components/network/RTCNetworkMonitor.h
Normal file
24
sdk/objc/components/network/RTCNetworkMonitor.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** Listens for NWPathMonitor updates and forwards the results to a C++
|
||||
* observer.
|
||||
*/
|
||||
@interface RTCNetworkMonitor : NSObject
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
109
sdk/objc/components/network/RTCNetworkMonitor.mm
Normal file
109
sdk/objc/components/network/RTCNetworkMonitor.mm
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import "RTCNetworkMonitor+Private.h"
|
||||
|
||||
#import <Network/Network.h>
|
||||
|
||||
#import "base/RTCLogging.h"
|
||||
#import "helpers/RTCDispatcher+Private.h"
|
||||
|
||||
namespace {
|
||||
|
||||
rtc::AdapterType AdapterTypeFromInterfaceType(nw_interface_type_t interfaceType) {
|
||||
rtc::AdapterType adapterType = rtc::ADAPTER_TYPE_UNKNOWN;
|
||||
switch (interfaceType) {
|
||||
case nw_interface_type_other:
|
||||
adapterType = rtc::ADAPTER_TYPE_UNKNOWN;
|
||||
break;
|
||||
case nw_interface_type_wifi:
|
||||
adapterType = rtc::ADAPTER_TYPE_WIFI;
|
||||
break;
|
||||
case nw_interface_type_cellular:
|
||||
adapterType = rtc::ADAPTER_TYPE_CELLULAR;
|
||||
break;
|
||||
case nw_interface_type_wired:
|
||||
adapterType = rtc::ADAPTER_TYPE_ETHERNET;
|
||||
break;
|
||||
case nw_interface_type_loopback:
|
||||
adapterType = rtc::ADAPTER_TYPE_LOOPBACK;
|
||||
break;
|
||||
default:
|
||||
adapterType = rtc::ADAPTER_TYPE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
return adapterType;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@implementation RTCNetworkMonitor {
|
||||
webrtc::NetworkMonitorObserver *_observer;
|
||||
nw_path_monitor_t _pathMonitor;
|
||||
dispatch_queue_t _monitorQueue;
|
||||
}
|
||||
|
||||
- (instancetype)initWithObserver:(webrtc::NetworkMonitorObserver *)observer {
|
||||
RTC_DCHECK(observer);
|
||||
if (self = [super init]) {
|
||||
_observer = observer;
|
||||
if (@available(iOS 12, *)) {
|
||||
_pathMonitor = nw_path_monitor_create();
|
||||
if (_pathMonitor == nil) {
|
||||
RTCLog(@"nw_path_monitor_create failed.");
|
||||
return nil;
|
||||
}
|
||||
RTCLog(@"NW path monitor created.");
|
||||
__weak RTCNetworkMonitor *weakSelf = self;
|
||||
nw_path_monitor_set_update_handler(_pathMonitor, ^(nw_path_t path) {
|
||||
if (weakSelf == nil) {
|
||||
return;
|
||||
}
|
||||
RTCNetworkMonitor *strongSelf = weakSelf;
|
||||
RTCLog(@"NW path monitor: updated.");
|
||||
nw_path_status_t status = nw_path_get_status(path);
|
||||
if (status == nw_path_status_invalid) {
|
||||
RTCLog(@"NW path monitor status: invalid.");
|
||||
} else if (status == nw_path_status_unsatisfied) {
|
||||
RTCLog(@"NW path monitor status: unsatisfied.");
|
||||
} else if (status == nw_path_status_satisfied) {
|
||||
RTCLog(@"NW path monitor status: satisfied.");
|
||||
} else if (status == nw_path_status_satisfiable) {
|
||||
RTCLog(@"NW path monitor status: satisfiable.");
|
||||
}
|
||||
std::map<std::string, rtc::AdapterType> *map =
|
||||
new std::map<std::string, rtc::AdapterType>();
|
||||
nw_path_enumerate_interfaces(
|
||||
path, (nw_path_enumerate_interfaces_block_t) ^ (nw_interface_t interface) {
|
||||
const char *name = nw_interface_get_name(interface);
|
||||
nw_interface_type_t interfaceType = nw_interface_get_type(interface);
|
||||
RTCLog(@"NW path monitor available interface: %s", name);
|
||||
rtc::AdapterType adapterType = AdapterTypeFromInterfaceType(interfaceType);
|
||||
map->insert(std::pair<std::string, rtc::AdapterType>(name, adapterType));
|
||||
});
|
||||
strongSelf->_observer->OnPathUpdate(std::move(*map));
|
||||
delete map;
|
||||
});
|
||||
nw_path_monitor_set_queue(
|
||||
_pathMonitor,
|
||||
[RTC_OBJC_TYPE(RTCDispatcher) dispatchQueueForType:RTCDispatcherTypeNetworkMonitor]);
|
||||
nw_path_monitor_start(_pathMonitor);
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
if (@available(iOS 12, *)) {
|
||||
nw_path_monitor_cancel(_pathMonitor);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
@ -20,6 +20,8 @@ typedef NS_ENUM(NSInteger, RTCDispatcherQueueType) {
|
||||
RTCDispatcherTypeCaptureSession,
|
||||
// Used for operations on AVAudioSession.
|
||||
RTCDispatcherTypeAudioSession,
|
||||
// Used for operations on NWPathMonitor.
|
||||
RTCDispatcherTypeNetworkMonitor,
|
||||
};
|
||||
|
||||
/** Dispatcher that asynchronously dispatches blocks to a specific
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
static dispatch_queue_t kAudioSessionQueue = nil;
|
||||
static dispatch_queue_t kCaptureSessionQueue = nil;
|
||||
static dispatch_queue_t kNetworkMonitorQueue = nil;
|
||||
|
||||
@implementation RTC_OBJC_TYPE (RTCDispatcher)
|
||||
|
||||
@ -24,6 +25,8 @@ static dispatch_queue_t kCaptureSessionQueue = nil;
|
||||
kCaptureSessionQueue = dispatch_queue_create(
|
||||
"org.webrtc.RTCDispatcherCaptureSession",
|
||||
DISPATCH_QUEUE_SERIAL);
|
||||
kNetworkMonitorQueue =
|
||||
dispatch_queue_create("org.webrtc.RTCDispatcherNetworkMonitor", DISPATCH_QUEUE_SERIAL);
|
||||
});
|
||||
}
|
||||
|
||||
@ -54,6 +57,8 @@ static dispatch_queue_t kCaptureSessionQueue = nil;
|
||||
return kCaptureSessionQueue;
|
||||
case RTCDispatcherTypeAudioSession:
|
||||
return kAudioSessionQueue;
|
||||
case RTCDispatcherTypeNetworkMonitor:
|
||||
return kNetworkMonitorQueue;
|
||||
}
|
||||
}
|
||||
|
||||
|
24
sdk/objc/native/api/network_monitor_factory.h
Normal file
24
sdk/objc/native/api/network_monitor_factory.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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_API_NETWORK_MONITOR_FACTORY_H_
|
||||
#define SDK_OBJC_NATIVE_API_NETWORK_MONITOR_FACTORY_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "rtc_base/network_monitor_factory.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
std::unique_ptr<rtc::NetworkMonitorFactory> CreateNetworkMonitorFactory();
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // SDK_OBJC_NATIVE_API_NETWORK_MONITOR_FACTORY_H_
|
30
sdk/objc/native/api/network_monitor_factory.mm
Normal file
30
sdk/objc/native/api/network_monitor_factory.mm
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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 "network_monitor_factory.h"
|
||||
|
||||
#if defined(WEBRTC_IOS)
|
||||
#include "sdk/objc/native/src/objc_network_monitor.h"
|
||||
#endif
|
||||
|
||||
#include "rtc_base/logging.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
std::unique_ptr<rtc::NetworkMonitorFactory> CreateNetworkMonitorFactory() {
|
||||
RTC_LOG(LS_INFO) << __FUNCTION__;
|
||||
#if defined(WEBRTC_IOS)
|
||||
return std::make_unique<ObjCNetworkMonitorFactory>();
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
39
sdk/objc/native/src/network_monitor_observer.h
Normal file
39
sdk/objc/native/src/network_monitor_observer.h
Normal 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_
|
72
sdk/objc/native/src/objc_network_monitor.h
Normal file
72
sdk/objc/native/src/objc_network_monitor.h
Normal 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_
|
86
sdk/objc/native/src/objc_network_monitor.mm
Normal file
86
sdk/objc/native/src/objc_network_monitor.mm
Normal 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
|
Reference in New Issue
Block a user