xref: /aosp_15_r20/external/cronet/net/nqe/socket_watcher.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2016 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "net/nqe/socket_watcher.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
8*6777b538SAndroid Build Coastguard Worker #include "base/location.h"
9*6777b538SAndroid Build Coastguard Worker #include "base/task/single_thread_task_runner.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/time/tick_clock.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
12*6777b538SAndroid Build Coastguard Worker #include "net/base/ip_address.h"
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker namespace net::nqe::internal {
15*6777b538SAndroid Build Coastguard Worker 
16*6777b538SAndroid Build Coastguard Worker namespace {
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker // Generate a compact representation for |ip_addr|. For IPv4, all 32 bits
19*6777b538SAndroid Build Coastguard Worker // are used and for IPv6, the first 64 bits are used as the remote host
20*6777b538SAndroid Build Coastguard Worker // identifier.
CalculateIPHash(const IPAddress & ip_addr)21*6777b538SAndroid Build Coastguard Worker std::optional<IPHash> CalculateIPHash(const IPAddress& ip_addr) {
22*6777b538SAndroid Build Coastguard Worker   IPAddressBytes bytes = ip_addr.bytes();
23*6777b538SAndroid Build Coastguard Worker 
24*6777b538SAndroid Build Coastguard Worker   // For IPv4, the first four bytes are taken. For IPv6, the first 8 bytes are
25*6777b538SAndroid Build Coastguard Worker   // taken. For IPv4MappedIPv6, the last 4 bytes are taken.
26*6777b538SAndroid Build Coastguard Worker   int index_min = ip_addr.IsIPv4MappedIPv6() ? 12 : 0;
27*6777b538SAndroid Build Coastguard Worker   int index_max;
28*6777b538SAndroid Build Coastguard Worker   if (ip_addr.IsIPv4MappedIPv6())
29*6777b538SAndroid Build Coastguard Worker     index_max = 16;
30*6777b538SAndroid Build Coastguard Worker   else
31*6777b538SAndroid Build Coastguard Worker     index_max = ip_addr.IsIPv4() ? 4 : 8;
32*6777b538SAndroid Build Coastguard Worker 
33*6777b538SAndroid Build Coastguard Worker   DCHECK_LE(index_min, index_max);
34*6777b538SAndroid Build Coastguard Worker   DCHECK_GE(8, index_max - index_min);
35*6777b538SAndroid Build Coastguard Worker 
36*6777b538SAndroid Build Coastguard Worker   uint64_t result = 0ULL;
37*6777b538SAndroid Build Coastguard Worker   for (int i = index_min; i < index_max; ++i) {
38*6777b538SAndroid Build Coastguard Worker     result = result << 8;
39*6777b538SAndroid Build Coastguard Worker     result |= bytes[i];
40*6777b538SAndroid Build Coastguard Worker   }
41*6777b538SAndroid Build Coastguard Worker   return result;
42*6777b538SAndroid Build Coastguard Worker }
43*6777b538SAndroid Build Coastguard Worker 
44*6777b538SAndroid Build Coastguard Worker }  // namespace
45*6777b538SAndroid Build Coastguard Worker 
SocketWatcher(SocketPerformanceWatcherFactory::Protocol protocol,const IPAddress & address,base::TimeDelta min_notification_interval,bool allow_rtt_private_address,scoped_refptr<base::SingleThreadTaskRunner> task_runner,OnUpdatedRTTAvailableCallback updated_rtt_observation_callback,ShouldNotifyRTTCallback should_notify_rtt_callback,const base::TickClock * tick_clock)46*6777b538SAndroid Build Coastguard Worker SocketWatcher::SocketWatcher(
47*6777b538SAndroid Build Coastguard Worker     SocketPerformanceWatcherFactory::Protocol protocol,
48*6777b538SAndroid Build Coastguard Worker     const IPAddress& address,
49*6777b538SAndroid Build Coastguard Worker     base::TimeDelta min_notification_interval,
50*6777b538SAndroid Build Coastguard Worker     bool allow_rtt_private_address,
51*6777b538SAndroid Build Coastguard Worker     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
52*6777b538SAndroid Build Coastguard Worker     OnUpdatedRTTAvailableCallback updated_rtt_observation_callback,
53*6777b538SAndroid Build Coastguard Worker     ShouldNotifyRTTCallback should_notify_rtt_callback,
54*6777b538SAndroid Build Coastguard Worker     const base::TickClock* tick_clock)
55*6777b538SAndroid Build Coastguard Worker     : protocol_(protocol),
56*6777b538SAndroid Build Coastguard Worker       task_runner_(std::move(task_runner)),
57*6777b538SAndroid Build Coastguard Worker       updated_rtt_observation_callback_(updated_rtt_observation_callback),
58*6777b538SAndroid Build Coastguard Worker       should_notify_rtt_callback_(should_notify_rtt_callback),
59*6777b538SAndroid Build Coastguard Worker       rtt_notifications_minimum_interval_(min_notification_interval),
60*6777b538SAndroid Build Coastguard Worker       allow_rtt_private_address_(allow_rtt_private_address),
61*6777b538SAndroid Build Coastguard Worker       run_rtt_callback_(allow_rtt_private_address ||
62*6777b538SAndroid Build Coastguard Worker                         address.IsPubliclyRoutable()),
63*6777b538SAndroid Build Coastguard Worker       tick_clock_(tick_clock),
64*6777b538SAndroid Build Coastguard Worker       host_(CalculateIPHash(address)) {
65*6777b538SAndroid Build Coastguard Worker   DCHECK(tick_clock_);
66*6777b538SAndroid Build Coastguard Worker   DCHECK(last_rtt_notification_.is_null());
67*6777b538SAndroid Build Coastguard Worker }
68*6777b538SAndroid Build Coastguard Worker 
69*6777b538SAndroid Build Coastguard Worker SocketWatcher::~SocketWatcher() = default;
70*6777b538SAndroid Build Coastguard Worker 
ShouldNotifyUpdatedRTT() const71*6777b538SAndroid Build Coastguard Worker bool SocketWatcher::ShouldNotifyUpdatedRTT() const {
72*6777b538SAndroid Build Coastguard Worker   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
73*6777b538SAndroid Build Coastguard Worker 
74*6777b538SAndroid Build Coastguard Worker   if (!run_rtt_callback_)
75*6777b538SAndroid Build Coastguard Worker     return false;
76*6777b538SAndroid Build Coastguard Worker 
77*6777b538SAndroid Build Coastguard Worker   const base::TimeTicks now = tick_clock_->NowTicks();
78*6777b538SAndroid Build Coastguard Worker 
79*6777b538SAndroid Build Coastguard Worker   if (task_runner_->RunsTasksInCurrentSequence()) {
80*6777b538SAndroid Build Coastguard Worker     // Enables socket watcher to send more frequent RTT observations when very
81*6777b538SAndroid Build Coastguard Worker     // few sockets are receiving data.
82*6777b538SAndroid Build Coastguard Worker     if (should_notify_rtt_callback_.Run(now))
83*6777b538SAndroid Build Coastguard Worker       return true;
84*6777b538SAndroid Build Coastguard Worker   }
85*6777b538SAndroid Build Coastguard Worker 
86*6777b538SAndroid Build Coastguard Worker   // Do not allow incoming notifications if the last notification was more
87*6777b538SAndroid Build Coastguard Worker   // recent than |rtt_notifications_minimum_interval_| ago. This helps in
88*6777b538SAndroid Build Coastguard Worker   // reducing the overhead of obtaining the RTT values.
89*6777b538SAndroid Build Coastguard Worker   // Enables a socket watcher to send RTT observation, helps in reducing
90*6777b538SAndroid Build Coastguard Worker   // starvation by allowing every socket watcher to notify at least one RTT
91*6777b538SAndroid Build Coastguard Worker   // notification every |rtt_notifications_minimum_interval_| duration.
92*6777b538SAndroid Build Coastguard Worker   return now - last_rtt_notification_ >= rtt_notifications_minimum_interval_;
93*6777b538SAndroid Build Coastguard Worker }
94*6777b538SAndroid Build Coastguard Worker 
OnUpdatedRTTAvailable(const base::TimeDelta & rtt)95*6777b538SAndroid Build Coastguard Worker void SocketWatcher::OnUpdatedRTTAvailable(const base::TimeDelta& rtt) {
96*6777b538SAndroid Build Coastguard Worker   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
97*6777b538SAndroid Build Coastguard Worker 
98*6777b538SAndroid Build Coastguard Worker   // tcp_socket_posix may sometimes report RTT as 1 microsecond when the RTT was
99*6777b538SAndroid Build Coastguard Worker   // actually invalid. See:
100*6777b538SAndroid Build Coastguard Worker   // https://cs.chromium.org/chromium/src/net/socket/tcp_socket_posix.cc?rcl=7ad660e34f2a996e381a85b2a515263003b0c171&l=106.
101*6777b538SAndroid Build Coastguard Worker   // Connections to private address eg localhost because they typically have
102*6777b538SAndroid Build Coastguard Worker   // small rtt.
103*6777b538SAndroid Build Coastguard Worker   if (!allow_rtt_private_address_ && rtt <= base::Microseconds(1)) {
104*6777b538SAndroid Build Coastguard Worker     return;
105*6777b538SAndroid Build Coastguard Worker   }
106*6777b538SAndroid Build Coastguard Worker 
107*6777b538SAndroid Build Coastguard Worker   if (!first_quic_rtt_notification_received_ &&
108*6777b538SAndroid Build Coastguard Worker       protocol_ == SocketPerformanceWatcherFactory::PROTOCOL_QUIC) {
109*6777b538SAndroid Build Coastguard Worker     // First RTT sample from QUIC connections may be synthetically generated,
110*6777b538SAndroid Build Coastguard Worker     // and may not reflect the actual network quality.
111*6777b538SAndroid Build Coastguard Worker     first_quic_rtt_notification_received_ = true;
112*6777b538SAndroid Build Coastguard Worker     return;
113*6777b538SAndroid Build Coastguard Worker   }
114*6777b538SAndroid Build Coastguard Worker 
115*6777b538SAndroid Build Coastguard Worker   last_rtt_notification_ = tick_clock_->NowTicks();
116*6777b538SAndroid Build Coastguard Worker   task_runner_->PostTask(
117*6777b538SAndroid Build Coastguard Worker       FROM_HERE,
118*6777b538SAndroid Build Coastguard Worker       base::BindOnce(updated_rtt_observation_callback_, protocol_, rtt, host_));
119*6777b538SAndroid Build Coastguard Worker }
120*6777b538SAndroid Build Coastguard Worker 
OnConnectionChanged()121*6777b538SAndroid Build Coastguard Worker void SocketWatcher::OnConnectionChanged() {
122*6777b538SAndroid Build Coastguard Worker   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
123*6777b538SAndroid Build Coastguard Worker }
124*6777b538SAndroid Build Coastguard Worker 
125*6777b538SAndroid Build Coastguard Worker }  // namespace net::nqe::internal
126