// Copyright 2018 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef SERVICES_NETWORK_WEBSOCKET_THROTTLER_H_ #define SERVICES_NETWORK_WEBSOCKET_THROTTLER_H_ #include #include #include #include "base/component_export.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" #include "base/timer/timer.h" namespace network { // WebSocketPerProcessThrottler provies a throttling functionality per // renderer process. See https://goo.gl/tldFNn. class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocketPerProcessThrottler final { public: // A PendingConnection represents a connection that has not finished a // handshake. // // Destroying a PendingConnection whose OnCompleteHandshake has not been // called represents a handshake failure (including going away during // handshake). class COMPONENT_EXPORT(NETWORK_SERVICE) PendingConnection final { public: // |throttler| cannot be null. explicit PendingConnection( base::WeakPtr throttler); PendingConnection(PendingConnection&& other); ~PendingConnection(); // Called when the hansdhake finishes sucessfully. void OnCompleteHandshake(); private: base::WeakPtr throttler_; DISALLOW_COPY_AND_ASSIGN(PendingConnection); }; WebSocketPerProcessThrottler(); ~WebSocketPerProcessThrottler(); // Returns if there are too many pending connections. bool HasTooManyPendingConnections() const { return num_pending_connections_ >= kMaxPendingWebSocketConnections; } // Returns the delay which should be used to throttle opening websocket // connections. base::TimeDelta CalculateDelay() const; // Issues an object which represents a pending connection. PendingConnection IssuePendingConnectionTracker(); // Returns true if this throttler is clean, i.e., we can restore the internal // state by simply creating a new object. bool IsClean() const; // Copies the succeeded / failed counters for the current period to the // ones for the previous period, and zeroes them. void Roll(); int64_t num_pending_connections() const { return num_pending_connections_; } int64_t num_current_succeeded_connections() const { return num_current_succeeded_connections_; } int64_t num_previous_succeeded_connections() const { return num_previous_succeeded_connections_; } int64_t num_current_failed_connections() const { return num_current_failed_connections_; } int64_t num_previous_failed_connections() const { return num_previous_failed_connections_; } private: // The current number of pending connections. int num_pending_connections_ = 0; // The number of handshakes that failed in the clurrent and previous time // period. int64_t num_current_succeeded_connections_ = 0; int64_t num_previous_succeeded_connections_ = 0; // The number of handshakes that succeeded in the current and previous time // period. int64_t num_current_failed_connections_ = 0; int64_t num_previous_failed_connections_ = 0; static constexpr int kMaxPendingWebSocketConnections = 255; base::WeakPtrFactory weak_factory_; DISALLOW_COPY_AND_ASSIGN(WebSocketPerProcessThrottler); }; // This class is for throttling WebSocket connections. WebSocketThrottler is // a set of per-renderer throttlers. // This class is only used in the network service. content::WebSocketManager // uses WebSocketPerProcessThrottler directly. class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocketThrottler final { public: using PendingConnection = WebSocketPerProcessThrottler::PendingConnection; WebSocketThrottler(); ~WebSocketThrottler(); // Returns true if there are too many pending connections for |process_id|. bool HasTooManyPendingConnections(int process_id) const; // Calculates connection delay for |process_id|. base::TimeDelta CalculateDelay(int process_id) const; // Returns a pending connection for |process_id|. This function can be called // only when |HasTooManyPendingConnections(process_id)| is false. PendingConnection IssuePendingConnectionTracker(int process_id); size_t GetSizeForTesting() const { return per_process_throttlers_.size(); } private: void OnTimer(); std::map> per_process_throttlers_; base::RepeatingTimer throttling_period_timer_; DISALLOW_COPY_AND_ASSIGN(WebSocketThrottler); }; } // namespace network #endif // SERVICES_NETWORK_WEBSOCKET_THROTTLER_H_