blob: 2b7eb71e25140df5e0b74576ff8124be209fd7c2 [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_SOCKET_SOCKET_POOL_ADDITIONAL_CAPACITY_H_
#define NET_SOCKET_SOCKET_POOL_ADDITIONAL_CAPACITY_H_
#include <string>
#include "base/strings/stringprintf.h"
#include "net/base/net_export.h"
namespace net {
// Socket pools update their state before every socket allocation and release.
enum class SocketPoolState {
// Uncapped pools can allocate or release sockets.
kUncapped,
// Capped pools cannot allocate sockets, but can release them.
kCapped
};
// This class encapsulates the logic for the additional TCP Socket Pool capacity
// allocated (and randomized) to prevent cross-site state tracking.
// See crbug.com/415691664 for more details.
class NET_EXPORT_PRIVATE SocketPoolAdditionalCapacity {
public:
// This initializes using values from kTcpSocketPoolLimitRandomization.
static SocketPoolAdditionalCapacity Create();
static SocketPoolAdditionalCapacity CreateForTest(double base,
int capacity,
double minimum,
double noise);
// Calculates the next `SocketPoolState` before the allocation of a socket.
// `sockets_in_use` should be counted pre-allocation and `socket_soft_cap`
// is likely being passed down from `g_max_sockets_per_pool`.
SocketPoolState NextStateBeforeAllocation(SocketPoolState current_state,
int sockets_in_use,
int socket_soft_cap) const;
// Calculates the next `SocketPoolState` after the release of a socket.
// `sockets_in_use` should be counted post-release and `socket_soft_cap`
// is likely being passed down from `g_max_sockets_per_pool`.
SocketPoolState NextStateAfterRelease(SocketPoolState current_state,
int sockets_in_use,
int socket_soft_cap) const;
explicit operator std::string() const {
return base::StringPrintf(
"SocketPoolAdditionalCapacity(base:%e,capacity:%i,minimum:%e,noise:%e)",
base_, capacity_, minimum_, noise_);
}
friend bool operator==(const SocketPoolAdditionalCapacity& lhs,
const SocketPoolAdditionalCapacity& rhs) {
return lhs.base_ == rhs.base_ && lhs.capacity_ == rhs.capacity_ &&
lhs.minimum_ == rhs.minimum_ && lhs.noise_ == rhs.noise_;
}
private:
enum class SocketPoolAction { kAllocation, kRelease };
static void LogStateTransition(SocketPoolAction action,
SocketPoolState current_state,
SocketPoolState next_state,
int sockets_in_use);
SocketPoolAdditionalCapacity() = default;
SocketPoolAdditionalCapacity(double base,
int capacity,
double minimum,
double noise);
// Helper for NextStateBeforeAllocation to avoid duplicate logging code.
SocketPoolState NextStateBeforeAllocationImpl(SocketPoolState current_state,
int sockets_in_use,
int socket_soft_cap) const;
// Helper for NextStateAfterRelease to avoid duplicate logging code.
SocketPoolState NextStateAfterReleaseImpl(SocketPoolState current_state,
int sockets_in_use,
int socket_soft_cap) const;
// This helper function for `NextStateBefore(Allocation|Release)` handles
// common logic. Returns a SocketPoolState if the common logic is controlling,
// and std::nullopt otherwise.
std::optional<SocketPoolState> NextStateCommonImpl(int sockets_in_use,
int socket_soft_cap) const;
// Unlike other functions in this class, this one will CHECK on invalid
// constants and inputs. As such, all validation must be performed before we
// get to this stage. The actual way this function rolls dice are quite
// complex, please see the implementation for details.
// `actions_taken` must be between 0 and `capacity_`, and is the
// amount of `capacity_` already allocated for `NextStateBeforeAllocationImpl`
// and the amount of `capacity_` free for `NextStateAfterReleaseImpl`. This is
// done to ensure the probability converges toward 1 correctly for each.
bool ShouldTransitionState(SocketPoolAction action, int actions_taken) const;
// See the implementation of `ShouldTransitionState` for how these constants
// are used and bound in calculating the probability of a state transition.
double base_ = 0.0;
int capacity_ = 0;
double minimum_ = 0.0;
double noise_ = 0.0;
};
} // namespace net
#endif // NET_SOCKET_SOCKET_POOL_ADDITIONAL_CAPACITY_H_