1 // Copyright 2020 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 #ifndef NET_SOCKET_UDP_SOCKET_GLOBAL_LIMITS_H_ 6 #define NET_SOCKET_UDP_SOCKET_GLOBAL_LIMITS_H_ 7 8 #include "net/base/net_errors.h" 9 #include "net/base/net_export.h" 10 11 namespace net { 12 13 // Helper class for RAII-style management of the global count of "open UDP 14 // sockets" [1] in the process. 15 // 16 // Keeping OwnedUDPSocketCount alive increases the global socket counter by 1. 17 // When it goes out of scope - or is explicitly Reset() - the reference is 18 // returned to the global counter. 19 class NET_EXPORT OwnedUDPSocketCount { 20 public: 21 // The default constructor builds an empty OwnedUDPSocketCount (does not own a 22 // count). 23 OwnedUDPSocketCount(); 24 25 // Any count held by OwnedUDPSocketCount is transferred when moving. 26 OwnedUDPSocketCount(OwnedUDPSocketCount&&); 27 OwnedUDPSocketCount& operator=(OwnedUDPSocketCount&&); 28 29 // This is a move-only type. 30 OwnedUDPSocketCount(const OwnedUDPSocketCount&) = delete; 31 OwnedUDPSocketCount& operator=(const OwnedUDPSocketCount&) = delete; 32 33 ~OwnedUDPSocketCount(); 34 35 // Returns false if this instance "owns" a socket count. In 36 // other words, when |empty()|, destruction of |this| will 37 // not change the global socket count. empty()38 bool empty() const { return empty_; } 39 40 // Resets |this| to an empty state (|empty()| becomes true after 41 // calling this). If |this| was previously |!empty()|, the global 42 // socket count will be decremented. 43 void Reset(); 44 45 private: 46 // Only TryAcquireGlobalUDPSocketCount() is allowed to construct a non-empty 47 // OwnedUDPSocketCount. 48 friend NET_EXPORT OwnedUDPSocketCount TryAcquireGlobalUDPSocketCount(); 49 explicit OwnedUDPSocketCount(bool empty); 50 51 bool empty_; 52 }; 53 54 // Attempts to increase the global "open UDP socket" [1] count. 55 // 56 // * On failure returns an OwnedUDPSocketCount that is |empty()|. This happens 57 // if the global socket limit has been reached. 58 // * On success returns an OwnedUDPSocketCount that is |!empty()|. This 59 // OwnedUDPSocketCount should be kept alive until the socket resource is 60 // released. 61 // 62 // [1] For simplicity, an "open UDP socket" is defined as a net::UDPSocket that 63 // successfully called Open(), and has not yet called Close(). This is 64 // analogous to the number of open platform socket handles, and in practice 65 // should also be a good proxy for the number of consumed UDP ports. 66 [[nodiscard]] NET_EXPORT OwnedUDPSocketCount TryAcquireGlobalUDPSocketCount(); 67 68 // Returns the current count of open UDP sockets (for testing only). 69 NET_EXPORT int GetGlobalUDPSocketCountForTesting(); 70 71 } // namespace net 72 73 #endif // NET_SOCKET_UDP_SOCKET_GLOBAL_LIMITS_H_ 74