| // Copyright 2024 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_HTTP_HTTP_STREAM_POOL_GROUP_H_ |
| #define NET_HTTP_HTTP_STREAM_POOL_GROUP_H_ |
| |
| #include <list> |
| #include <memory> |
| #include <vector> |
| |
| #include "base/memory/raw_ptr.h" |
| #include "base/time/time.h" |
| #include "net/base/load_timing_info.h" |
| #include "net/base/net_export.h" |
| #include "net/http/http_stream_key.h" |
| #include "net/http/http_stream_pool.h" |
| #include "net/http/http_stream_request.h" |
| #include "net/spdy/spdy_session_key.h" |
| |
| namespace net { |
| |
| class HttpNetworkSession; |
| class HttpStream; |
| class HttpStreamPoolHandle; |
| class StreamSocket; |
| |
| // Maintains active/idle text-based HTTP streams. |
| class HttpStreamPool::Group { |
| public: |
| // The same timeout as ClientSocketPool::used_idle_socket_timeout(). |
| static constexpr base::TimeDelta kUsedIdleStreamSocketTimeout = |
| base::Seconds(300); |
| |
| // The same timeout as |
| // ClientSocketPoolManager::unused_idle_socket_timeout(). |
| static constexpr base::TimeDelta kUnusedIdleStreamSocketTimeout = |
| base::Seconds(60); |
| |
| Group(HttpStreamPool* pool, |
| HttpStreamKey stream_key, |
| SpdySessionKey spdy_session_key); |
| |
| Group(const Group&) = delete; |
| Group& operator=(const Group&) = delete; |
| |
| ~Group(); |
| |
| const HttpStreamKey& stream_key() const { return stream_key_; } |
| |
| const SpdySessionKey& spdy_session_key() const { return spdy_session_key_; } |
| |
| HttpStreamPool* pool() { return pool_; } |
| const HttpStreamPool* pool() const { return pool_; } |
| |
| HttpNetworkSession* http_network_session() const { |
| return pool_->http_network_session(); |
| } |
| |
| const NetLogWithSource& net_log() { return net_log_; } |
| |
| // Creates an HttpStreamRequest. Will call delegate's methods. See the |
| // comments of HttpStreamRequest::Delegate methods for details. |
| // TODO(crbug.com/346835898): Support QUIC. |
| std::unique_ptr<HttpStreamRequest> RequestStream( |
| HttpStreamRequest::Delegate* delegate, |
| RequestPriority priority, |
| const std::vector<SSLConfig::CertAndStatus>& allowed_bad_certs, |
| bool enable_ip_based_pooling, |
| const NetLogWithSource& net_log); |
| |
| // Creates idle streams or sessions for `num_streams` be opened. |
| // Note that this method finishes synchronously, or `callback` is called, once |
| // `this` has enough streams/sessions for `num_streams` be opened. This means |
| // that when there are two preconnect requests with `num_streams = 1`, all |
| // callbacks are invoked when one stream/session is established (not two). |
| int Preconnect(size_t num_streams, CompletionOnceCallback callback); |
| |
| // Creates an HttpStreamPoolHandle from `socket`. Call sites must ensure that |
| // the number of active streams do not exceed the global/per-group limits. |
| std::unique_ptr<HttpStreamPoolHandle> CreateHandle( |
| std::unique_ptr<StreamSocket> socket, |
| LoadTimingInfo::ConnectTiming connect_timing); |
| |
| // Creates a text-based HttpStream from `socket`. Call sites must ensure that |
| // the number of active streams do not exceed the global/per-group limits. |
| // `socket` must not be negotiated to use HTTP/2. |
| std::unique_ptr<HttpStream> CreateTextBasedStream( |
| std::unique_ptr<StreamSocket> socket, |
| LoadTimingInfo::ConnectTiming connect_timing); |
| |
| // Releases a StreamSocket that was used to create a text-based HttpStream. |
| void ReleaseStreamSocket(std::unique_ptr<StreamSocket> socket, |
| int64_t generation); |
| |
| // Adds `socket` as an idle StreamSocket for text-based HttpStream. Call sites |
| // must ensure that the number of idle streams do not exceed the global/per- |
| // group limits. |
| // `socket` must not be negotiated to use HTTP/2. |
| void AddIdleStreamSocket(std::unique_ptr<StreamSocket> socket); |
| |
| // Retrieves an existing idle StreamSocket. Returns nullptr when there is no |
| // idle stream. |
| std::unique_ptr<StreamSocket> GetIdleStreamSocket(); |
| |
| // Tries to process a pending request. |
| void ProcessPendingRequest(); |
| |
| // Closes one idle stream socket. Returns true if it closed a stream. |
| bool CloseOneIdleStreamSocket(); |
| |
| // Returns the number of idle streams. |
| size_t IdleStreamSocketCount() const { return idle_stream_sockets_.size(); } |
| |
| // Returns the number of active streams. |
| size_t ActiveStreamSocketCount() const; |
| |
| bool ReachedMaxStreamLimit() const; |
| |
| // Returns the highest pending request priority if the group is stalled due to |
| // the per-pool limit, not the per-group limit. |
| std::optional<RequestPriority> GetPriorityIfStalledByPoolLimit() const; |
| |
| // Increments the generation of this group. Closes idle streams. Streams |
| // handed out before this increment won't be reused. Cancels in-flight |
| // connection attempts. |
| void Refresh(); |
| |
| // Cancels all on-going requests. |
| void CancelRequests(int error); |
| |
| // Called when the in-flight job has completed. |
| void OnJobComplete(); |
| |
| void CleanupTimedoutIdleStreamSocketsForTesting(); |
| |
| Job* GetJobForTesting() const { return in_flight_job_.get(); } |
| |
| private: |
| struct IdleStreamSocket { |
| IdleStreamSocket(std::unique_ptr<StreamSocket> stream_socket, |
| base::TimeTicks start_time); |
| ~IdleStreamSocket(); |
| |
| IdleStreamSocket(const IdleStreamSocket&) = delete; |
| IdleStreamSocket& operator=(const IdleStreamSocket&) = delete; |
| |
| std::unique_ptr<StreamSocket> stream_socket; |
| base::TimeTicks time_became_idle; |
| }; |
| |
| enum class CleanupMode { |
| // Clean up only timed out idle streams. |
| kTimeoutOnly, |
| // Clean up all idle streams. |
| kForce, |
| }; |
| |
| void CleanupIdleStreamSockets(CleanupMode mode); |
| |
| void EnsureInFlightJob(); |
| |
| void MaybeComplete(); |
| |
| const raw_ptr<HttpStreamPool> pool_; |
| const HttpStreamKey stream_key_; |
| const SpdySessionKey spdy_session_key_; |
| const NetLogWithSource net_log_; |
| |
| size_t handed_out_stream_count_ = 0; |
| int64_t generation_ = 0; |
| std::list<IdleStreamSocket> idle_stream_sockets_; |
| |
| std::unique_ptr<Job> in_flight_job_; |
| }; |
| |
| } // namespace net |
| |
| #endif // NET_HTTP_HTTP_STREAM_POOL_GROUP_H_ |