// Copyright 2020 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_UDP_SOCKET_GLOBAL_LIMITS_H_ #define NET_SOCKET_UDP_SOCKET_GLOBAL_LIMITS_H_ #include "net/base/net_errors.h" #include "net/base/net_export.h" namespace net { // Helper class for RAII-style management of the global count of "open UDP // sockets" [1] in the process. // // Keeping OwnedUDPSocketCount alive increases the global socket counter by 1. // When it goes out of scope - or is explicitly Reset() - the reference is // returned to the global counter. class NET_EXPORT OwnedUDPSocketCount { public: // The default constructor builds an empty OwnedUDPSocketCount (does not own a // count). OwnedUDPSocketCount(); // Any count held by OwnedUDPSocketCount is transferred when moving. OwnedUDPSocketCount(OwnedUDPSocketCount&&); OwnedUDPSocketCount& operator=(OwnedUDPSocketCount&&); // This is a move-only type. OwnedUDPSocketCount(const OwnedUDPSocketCount&) = delete; OwnedUDPSocketCount& operator=(const OwnedUDPSocketCount&) = delete; ~OwnedUDPSocketCount(); // Returns false if this instance "owns" a socket count. In // other words, when |empty()|, destruction of |this| will // not change the global socket count. bool empty() const { return empty_; } // Resets |this| to an empty state (|empty()| becomes true after // calling this). If |this| was previously |!empty()|, the global // socket count will be decremented. void Reset(); private: // Only TryAcquireGlobalUDPSocketCount() is allowed to construct a non-empty // OwnedUDPSocketCount. friend NET_EXPORT OwnedUDPSocketCount TryAcquireGlobalUDPSocketCount(); explicit OwnedUDPSocketCount(bool empty); bool empty_; }; // Attempts to increase the global "open UDP socket" [1] count. // // * On failure returns an OwnedUDPSocketCount that is |empty()|. This happens // if the global socket limit has been reached. // * On success returns an OwnedUDPSocketCount that is |!empty()|. This // OwnedUDPSocketCount should be kept alive until the socket resource is // released. // // [1] For simplicity, an "open UDP socket" is defined as a net::UDPSocket that // successfully called Open(), and has not yet called Close(). This is // analogous to the number of open platform socket handles, and in practice // should also be a good proxy for the number of consumed UDP ports. [[nodiscard]] NET_EXPORT OwnedUDPSocketCount TryAcquireGlobalUDPSocketCount(); // Returns the current count of open UDP sockets (for testing only). NET_EXPORT int GetGlobalUDPSocketCountForTesting(); } // namespace net #endif // NET_SOCKET_UDP_SOCKET_GLOBAL_LIMITS_H_