xref: /aosp_15_r20/external/cronet/net/tools/net_watcher/net_watcher.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // This is a small utility that watches for and logs network changes.
6 // It prints out the current network connection type and proxy configuration
7 // upon startup and then prints out changes as they happen.
8 // It's useful for testing NetworkChangeNotifier and ProxyConfigService.
9 // The only command line option supported is --ignore-netif which is followed
10 // by a comma seperated list of network interfaces to ignore when computing
11 // connection type; this option is only supported on linux.
12 
13 #include <memory>
14 #include <string>
15 #include <unordered_set>
16 
17 #include "base/at_exit.h"
18 #include "base/command_line.h"
19 #include "base/compiler_specific.h"
20 #include "base/json/json_writer.h"
21 #include "base/logging.h"
22 #include "base/message_loop/message_pump_type.h"
23 #include "base/run_loop.h"
24 #include "base/strings/string_split.h"
25 #include "base/task/single_thread_task_executor.h"
26 #include "base/task/thread_pool/thread_pool_instance.h"
27 #include "base/values.h"
28 #include "build/build_config.h"
29 #include "build/chromeos_buildflags.h"
30 #include "net/base/network_change_notifier.h"
31 #include "net/proxy_resolution/proxy_config.h"
32 #include "net/proxy_resolution/proxy_config_service.h"
33 #include "net/proxy_resolution/proxy_config_with_annotation.h"
34 
35 #if BUILDFLAG(IS_LINUX)
36 #include "net/base/network_change_notifier_linux.h"
37 #endif
38 
39 #if BUILDFLAG(IS_APPLE)
40 #include "base/apple/scoped_nsautorelease_pool.h"
41 #endif
42 
43 namespace {
44 
45 // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
46 // of lacros-chrome is complete.
47 #if BUILDFLAG(IS_LINUX)
48 // Flag to specifies which network interfaces to ignore. Interfaces should
49 // follow as a comma seperated list.
50 const char kIgnoreNetifFlag[] = "ignore-netif";
51 #endif
52 
53 // Conversions from various network-related types to string.
54 
ConnectionTypeToString(net::NetworkChangeNotifier::ConnectionType type)55 const char* ConnectionTypeToString(
56     net::NetworkChangeNotifier::ConnectionType type) {
57   switch (type) {
58     case net::NetworkChangeNotifier::CONNECTION_UNKNOWN:
59       return "CONNECTION_UNKNOWN";
60     case net::NetworkChangeNotifier::CONNECTION_ETHERNET:
61       return "CONNECTION_ETHERNET";
62     case net::NetworkChangeNotifier::CONNECTION_WIFI:
63       return "CONNECTION_WIFI";
64     case net::NetworkChangeNotifier::CONNECTION_2G:
65       return "CONNECTION_2G";
66     case net::NetworkChangeNotifier::CONNECTION_3G:
67       return "CONNECTION_3G";
68     case net::NetworkChangeNotifier::CONNECTION_4G:
69       return "CONNECTION_4G";
70     case net::NetworkChangeNotifier::CONNECTION_5G:
71       return "CONNECTION_5G";
72     case net::NetworkChangeNotifier::CONNECTION_NONE:
73       return "CONNECTION_NONE";
74     case net::NetworkChangeNotifier::CONNECTION_BLUETOOTH:
75       return "CONNECTION_BLUETOOTH";
76     default:
77       return "CONNECTION_UNEXPECTED";
78   }
79 }
80 
ProxyConfigToString(const net::ProxyConfig & config)81 std::string ProxyConfigToString(const net::ProxyConfig& config) {
82   base::Value config_value = config.ToValue();
83   std::string str;
84   base::JSONWriter::Write(config_value, &str);
85   return str;
86 }
87 
ConfigAvailabilityToString(net::ProxyConfigService::ConfigAvailability availability)88 const char* ConfigAvailabilityToString(
89     net::ProxyConfigService::ConfigAvailability availability) {
90   switch (availability) {
91     case net::ProxyConfigService::CONFIG_PENDING:
92       return "CONFIG_PENDING";
93     case net::ProxyConfigService::CONFIG_VALID:
94       return "CONFIG_VALID";
95     case net::ProxyConfigService::CONFIG_UNSET:
96       return "CONFIG_UNSET";
97     default:
98       return "CONFIG_UNEXPECTED";
99   }
100 }
101 
102 // The main observer class that logs network events.
103 class NetWatcher :
104       public net::NetworkChangeNotifier::IPAddressObserver,
105       public net::NetworkChangeNotifier::ConnectionTypeObserver,
106       public net::NetworkChangeNotifier::DNSObserver,
107       public net::NetworkChangeNotifier::NetworkChangeObserver,
108       public net::ProxyConfigService::Observer {
109  public:
110   NetWatcher() = default;
111 
112   NetWatcher(const NetWatcher&) = delete;
113   NetWatcher& operator=(const NetWatcher&) = delete;
114 
115   ~NetWatcher() override = default;
116 
117   // net::NetworkChangeNotifier::IPAddressObserver implementation.
OnIPAddressChanged()118   void OnIPAddressChanged() override { LOG(INFO) << "OnIPAddressChanged()"; }
119 
120   // net::NetworkChangeNotifier::ConnectionTypeObserver implementation.
OnConnectionTypeChanged(net::NetworkChangeNotifier::ConnectionType type)121   void OnConnectionTypeChanged(
122       net::NetworkChangeNotifier::ConnectionType type) override {
123     LOG(INFO) << "OnConnectionTypeChanged("
124               << ConnectionTypeToString(type) << ")";
125   }
126 
127   // net::NetworkChangeNotifier::DNSObserver implementation.
OnDNSChanged()128   void OnDNSChanged() override { LOG(INFO) << "OnDNSChanged()"; }
129 
130   // net::NetworkChangeNotifier::NetworkChangeObserver implementation.
OnNetworkChanged(net::NetworkChangeNotifier::ConnectionType type)131   void OnNetworkChanged(
132       net::NetworkChangeNotifier::ConnectionType type) override {
133     LOG(INFO) << "OnNetworkChanged("
134               << ConnectionTypeToString(type) << ")";
135   }
136 
137   // net::ProxyConfigService::Observer implementation.
OnProxyConfigChanged(const net::ProxyConfigWithAnnotation & config,net::ProxyConfigService::ConfigAvailability availability)138   void OnProxyConfigChanged(
139       const net::ProxyConfigWithAnnotation& config,
140       net::ProxyConfigService::ConfigAvailability availability) override {
141     LOG(INFO) << "OnProxyConfigChanged(" << ProxyConfigToString(config.value())
142               << ", " << ConfigAvailabilityToString(availability) << ")";
143   }
144 };
145 
146 }  // namespace
147 
main(int argc,char * argv[])148 int main(int argc, char* argv[]) {
149 #if BUILDFLAG(IS_APPLE)
150   base::apple::ScopedNSAutoreleasePool pool;
151 #endif
152   base::AtExitManager exit_manager;
153   base::CommandLine::Init(argc, argv);
154   logging::LoggingSettings settings;
155   settings.logging_dest =
156       logging::LOG_TO_SYSTEM_DEBUG_LOG | logging::LOG_TO_STDERR;
157   logging::InitLogging(settings);
158 
159   // Just make the main task executor the network loop.
160   base::SingleThreadTaskExecutor io_task_executor(base::MessagePumpType::IO);
161 
162   base::ThreadPoolInstance::CreateAndStartWithDefaultParams("NetWatcher");
163 
164   NetWatcher net_watcher;
165 
166 #if BUILDFLAG(IS_LINUX)
167   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
168   std::string ignored_netifs_str =
169       command_line->GetSwitchValueASCII(kIgnoreNetifFlag);
170   std::unordered_set<std::string> ignored_interfaces;
171   if (!ignored_netifs_str.empty()) {
172     for (const std::string& ignored_netif :
173          base::SplitString(ignored_netifs_str, ",", base::TRIM_WHITESPACE,
174                            base::SPLIT_WANT_ALL)) {
175       LOG(INFO) << "Ignoring: " << ignored_netif;
176       ignored_interfaces.insert(ignored_netif);
177     }
178   }
179   auto network_change_notifier =
180       std::make_unique<net::NetworkChangeNotifierLinux>(ignored_interfaces);
181 #else
182   std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier(
183       net::NetworkChangeNotifier::CreateIfNeeded());
184 #endif
185 
186   // Use the network loop as the file loop also.
187   std::unique_ptr<net::ProxyConfigService> proxy_config_service(
188       net::ProxyConfigService::CreateSystemProxyConfigService(
189           io_task_executor.task_runner()));
190 
191   // Uses |network_change_notifier|.
192   net::NetworkChangeNotifier::AddIPAddressObserver(&net_watcher);
193   net::NetworkChangeNotifier::AddConnectionTypeObserver(&net_watcher);
194   net::NetworkChangeNotifier::AddDNSObserver(&net_watcher);
195   net::NetworkChangeNotifier::AddNetworkChangeObserver(&net_watcher);
196 
197   proxy_config_service->AddObserver(&net_watcher);
198 
199   LOG(INFO) << "Initial connection type: "
200             << ConnectionTypeToString(
201                    net::NetworkChangeNotifier::GetConnectionType());
202 
203   {
204     net::ProxyConfigWithAnnotation config;
205     const net::ProxyConfigService::ConfigAvailability availability =
206         proxy_config_service->GetLatestProxyConfig(&config);
207     LOG(INFO) << "Initial proxy config: " << ProxyConfigToString(config.value())
208               << ", " << ConfigAvailabilityToString(availability);
209   }
210 
211   LOG(INFO) << "Watching for network events...";
212 
213   // Start watching for events.
214   base::RunLoop().Run();
215 
216   proxy_config_service->RemoveObserver(&net_watcher);
217 
218   // Uses |network_change_notifier|.
219   net::NetworkChangeNotifier::RemoveDNSObserver(&net_watcher);
220   net::NetworkChangeNotifier::RemoveConnectionTypeObserver(&net_watcher);
221   net::NetworkChangeNotifier::RemoveIPAddressObserver(&net_watcher);
222   net::NetworkChangeNotifier::RemoveNetworkChangeObserver(&net_watcher);
223 
224   return 0;
225 }
226