xref: /aosp_15_r20/external/webrtc/sdk/objc/components/network/RTCNetworkMonitor.mm (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1/*
2 *  Copyright 2020 The WebRTC Project Authors. All rights reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#import "RTCNetworkMonitor+Private.h"
12
13#import <Network/Network.h>
14
15#import "base/RTCLogging.h"
16#import "helpers/RTCDispatcher+Private.h"
17
18#include "rtc_base/string_utils.h"
19
20namespace {
21
22rtc::AdapterType AdapterTypeFromInterfaceType(nw_interface_type_t interfaceType) {
23  rtc::AdapterType adapterType = rtc::ADAPTER_TYPE_UNKNOWN;
24  switch (interfaceType) {
25    case nw_interface_type_other:
26      adapterType = rtc::ADAPTER_TYPE_UNKNOWN;
27      break;
28    case nw_interface_type_wifi:
29      adapterType = rtc::ADAPTER_TYPE_WIFI;
30      break;
31    case nw_interface_type_cellular:
32      adapterType = rtc::ADAPTER_TYPE_CELLULAR;
33      break;
34    case nw_interface_type_wired:
35      adapterType = rtc::ADAPTER_TYPE_ETHERNET;
36      break;
37    case nw_interface_type_loopback:
38      adapterType = rtc::ADAPTER_TYPE_LOOPBACK;
39      break;
40    default:
41      adapterType = rtc::ADAPTER_TYPE_UNKNOWN;
42      break;
43  }
44  return adapterType;
45}
46
47}  // namespace
48
49@implementation RTCNetworkMonitor {
50  webrtc::NetworkMonitorObserver *_observer;
51  nw_path_monitor_t _pathMonitor;
52  dispatch_queue_t _monitorQueue;
53}
54
55- (instancetype)initWithObserver:(webrtc::NetworkMonitorObserver *)observer {
56  RTC_DCHECK(observer);
57  if (self = [super init]) {
58    _observer = observer;
59    if (@available(iOS 12, *)) {
60      _pathMonitor = nw_path_monitor_create();
61      if (_pathMonitor == nil) {
62        RTCLog(@"nw_path_monitor_create failed.");
63        return nil;
64      }
65      RTCLog(@"NW path monitor created.");
66      __weak RTCNetworkMonitor *weakSelf = self;
67      nw_path_monitor_set_update_handler(_pathMonitor, ^(nw_path_t path) {
68        if (weakSelf == nil) {
69          return;
70        }
71        RTCNetworkMonitor *strongSelf = weakSelf;
72        RTCLog(@"NW path monitor: updated.");
73        nw_path_status_t status = nw_path_get_status(path);
74        if (status == nw_path_status_invalid) {
75          RTCLog(@"NW path monitor status: invalid.");
76        } else if (status == nw_path_status_unsatisfied) {
77          RTCLog(@"NW path monitor status: unsatisfied.");
78        } else if (status == nw_path_status_satisfied) {
79          RTCLog(@"NW path monitor status: satisfied.");
80        } else if (status == nw_path_status_satisfiable) {
81          RTCLog(@"NW path monitor status: satisfiable.");
82        }
83        std::map<std::string, rtc::AdapterType, rtc::AbslStringViewCmp> *map =
84            new std::map<std::string, rtc::AdapterType, rtc::AbslStringViewCmp>();
85        nw_path_enumerate_interfaces(
86            path, (nw_path_enumerate_interfaces_block_t) ^ (nw_interface_t interface) {
87              const char *name = nw_interface_get_name(interface);
88              nw_interface_type_t interfaceType = nw_interface_get_type(interface);
89              RTCLog(@"NW path monitor available interface: %s", name);
90              rtc::AdapterType adapterType = AdapterTypeFromInterfaceType(interfaceType);
91              map->insert(std::pair<std::string, rtc::AdapterType>(name, adapterType));
92            });
93        @synchronized(strongSelf) {
94          webrtc::NetworkMonitorObserver *observer = strongSelf->_observer;
95          if (observer) {
96            observer->OnPathUpdate(std::move(*map));
97          }
98        }
99        delete map;
100      });
101      nw_path_monitor_set_queue(
102          _pathMonitor,
103          [RTC_OBJC_TYPE(RTCDispatcher) dispatchQueueForType:RTCDispatcherTypeNetworkMonitor]);
104      nw_path_monitor_start(_pathMonitor);
105    }
106  }
107  return self;
108}
109
110- (void)cancel {
111  if (@available(iOS 12, *)) {
112    nw_path_monitor_cancel(_pathMonitor);
113  }
114}
115- (void)stop {
116  [self cancel];
117  @synchronized(self) {
118    _observer = nil;
119  }
120}
121
122- (void)dealloc {
123  [self cancel];
124}
125
126@end
127