udp_socket_global_limits.cc 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include <limits>
  5. #include "base/atomic_ref_count.h"
  6. #include "base/no_destructor.h"
  7. #include "net/base/features.h"
  8. #include "net/socket/udp_socket_global_limits.h"
  9. namespace net {
  10. namespace {
  11. // Threadsafe singleton for tracking the process-wide count of UDP sockets.
  12. class GlobalUDPSocketCounts {
  13. public:
  14. GlobalUDPSocketCounts() = default;
  15. ~GlobalUDPSocketCounts() = delete;
  16. static GlobalUDPSocketCounts& Get() {
  17. static base::NoDestructor<GlobalUDPSocketCounts> singleton;
  18. return *singleton;
  19. }
  20. [[nodiscard]] bool TryAcquireSocket() {
  21. int previous = count_.Increment(1);
  22. if (previous >= GetMax()) {
  23. count_.Increment(-1);
  24. return false;
  25. }
  26. return true;
  27. }
  28. int GetMax() {
  29. if (base::FeatureList::IsEnabled(features::kLimitOpenUDPSockets))
  30. return features::kLimitOpenUDPSocketsMax.Get();
  31. return std::numeric_limits<int>::max();
  32. }
  33. void ReleaseSocket() { count_.Increment(-1); }
  34. int GetCountForTesting() { return count_.SubtleRefCountForDebug(); }
  35. private:
  36. base::AtomicRefCount count_{0};
  37. };
  38. } // namespace
  39. OwnedUDPSocketCount::OwnedUDPSocketCount() : OwnedUDPSocketCount(true) {}
  40. OwnedUDPSocketCount::OwnedUDPSocketCount(OwnedUDPSocketCount&& other) {
  41. *this = std::move(other);
  42. }
  43. OwnedUDPSocketCount& OwnedUDPSocketCount::operator=(
  44. OwnedUDPSocketCount&& other) {
  45. Reset();
  46. empty_ = other.empty_;
  47. other.empty_ = true;
  48. return *this;
  49. }
  50. OwnedUDPSocketCount::~OwnedUDPSocketCount() {
  51. Reset();
  52. }
  53. void OwnedUDPSocketCount::Reset() {
  54. if (!empty_) {
  55. GlobalUDPSocketCounts::Get().ReleaseSocket();
  56. empty_ = true;
  57. }
  58. }
  59. OwnedUDPSocketCount::OwnedUDPSocketCount(bool empty) : empty_(empty) {}
  60. OwnedUDPSocketCount TryAcquireGlobalUDPSocketCount() {
  61. bool success = GlobalUDPSocketCounts::Get().TryAcquireSocket();
  62. return OwnedUDPSocketCount(!success);
  63. }
  64. int GetGlobalUDPSocketCountForTesting() {
  65. return GlobalUDPSocketCounts::Get().GetCountForTesting();
  66. }
  67. } // namespace net