1 // Copyright 2024 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_HTTP_HTTP_STREAM_POOL_GROUP_H_ 6 #define NET_HTTP_HTTP_STREAM_POOL_GROUP_H_ 7 8 #include <list> 9 #include <memory> 10 #include <string_view> 11 #include <vector> 12 13 #include "base/memory/raw_ptr.h" 14 #include "base/memory/weak_ptr.h" 15 #include "base/time/time.h" 16 #include "base/types/expected.h" 17 #include "net/base/load_timing_info.h" 18 #include "net/base/net_export.h" 19 #include "net/http/http_stream_key.h" 20 #include "net/http/http_stream_pool.h" 21 #include "net/http/http_stream_pool_job.h" 22 #include "net/http/http_stream_request.h" 23 #include "net/quic/quic_session_alias_key.h" 24 #include "net/socket/stream_socket_handle.h" 25 #include "net/spdy/spdy_session_key.h" 26 #include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h" 27 #include "url/scheme_host_port.h" 28 29 namespace net { 30 31 class HttpNetworkSession; 32 class HttpStream; 33 class HttpStreamPoolHandle; 34 class StreamSocket; 35 36 // Maintains active/idle text-based HTTP streams. 37 class HttpStreamPool::Group { 38 public: 39 // The same timeout as ClientSocketPool::used_idle_socket_timeout(). 40 static constexpr base::TimeDelta kUsedIdleStreamSocketTimeout = 41 base::Seconds(300); 42 43 // The same timeout as 44 // ClientSocketPoolManager::unused_idle_socket_timeout(). 45 static constexpr base::TimeDelta kUnusedIdleStreamSocketTimeout = 46 base::Seconds(60); 47 48 Group(HttpStreamPool* pool, 49 HttpStreamKey stream_key, 50 std::optional<QuicSessionAliasKey> quic_session_alias_key); 51 52 Group(const Group&) = delete; 53 Group& operator=(const Group&) = delete; 54 55 ~Group(); 56 stream_key()57 const HttpStreamKey& stream_key() const { return stream_key_; } 58 spdy_session_key()59 const SpdySessionKey& spdy_session_key() const { return spdy_session_key_; } 60 quic_session_alias_key()61 const QuicSessionAliasKey& quic_session_alias_key() const { 62 return quic_session_alias_key_; 63 } 64 pool()65 HttpStreamPool* pool() { return pool_; } pool()66 const HttpStreamPool* pool() const { return pool_; } 67 http_network_session()68 HttpNetworkSession* http_network_session() const { 69 return pool_->http_network_session(); 70 } 71 net_log()72 const NetLogWithSource& net_log() { return net_log_; } 73 force_quic()74 bool force_quic() const { return force_quic_; } 75 76 // Creates a Job to attempt connection(s). We have separate methods for 77 // creating and starting a Job to ensure that the owner of the Job can 78 // properly manage the lifetime of the Job, even when StartJob() synchronously 79 // calls one of the delegate's methods. 80 std::unique_ptr<Job> CreateJob(Job::Delegate* delegate, 81 quic::ParsedQuicVersion quic_version, 82 NextProto expected_protocol, 83 const NetLogWithSource& net_log); 84 85 // Creates idle streams or sessions for `num_streams` be opened. 86 // Note that this method finishes synchronously, or `callback` is called, once 87 // `this` has enough streams/sessions for `num_streams` be opened. This means 88 // that when there are two preconnect requests with `num_streams = 1`, all 89 // callbacks are invoked when one stream/session is established (not two). 90 int Preconnect(size_t num_streams, 91 quic::ParsedQuicVersion quic_version, 92 CompletionOnceCallback callback); 93 94 // Creates an HttpStreamPoolHandle from `socket`. Call sites must ensure that 95 // the number of active streams do not exceed the global/per-group limits. 96 std::unique_ptr<HttpStreamPoolHandle> CreateHandle( 97 std::unique_ptr<StreamSocket> socket, 98 StreamSocketHandle::SocketReuseType reuse_type, 99 LoadTimingInfo::ConnectTiming connect_timing); 100 101 // Creates a text-based HttpStream from `socket`. Call sites must ensure that 102 // the number of active streams do not exceed the global/per-group limits. 103 // `socket` must not be negotiated to use HTTP/2. 104 std::unique_ptr<HttpStream> CreateTextBasedStream( 105 std::unique_ptr<StreamSocket> socket, 106 StreamSocketHandle::SocketReuseType reuse_type, 107 LoadTimingInfo::ConnectTiming connect_timing); 108 109 // Releases a StreamSocket that was used to create a text-based HttpStream. 110 void ReleaseStreamSocket(std::unique_ptr<StreamSocket> socket, 111 int64_t generation); 112 113 // Adds `socket` as an idle StreamSocket for text-based HttpStream. Call sites 114 // must ensure that the number of idle streams do not exceed the global/per- 115 // group limits. 116 // `socket` must not be negotiated to use HTTP/2. 117 void AddIdleStreamSocket(std::unique_ptr<StreamSocket> socket); 118 119 // Retrieves an existing idle StreamSocket. Returns nullptr when there is no 120 // idle stream. 121 std::unique_ptr<StreamSocket> GetIdleStreamSocket(); 122 123 // Tries to process a pending request. 124 void ProcessPendingRequest(); 125 126 // Closes one idle stream socket. Returns true if it closed a stream. Called 127 // when the pool reached the stream count limit. 128 bool CloseOneIdleStreamSocket(); 129 130 // Returns the number of handed out streams. HandedOutStreamSocketCount()131 size_t HandedOutStreamSocketCount() const { return handed_out_stream_count_; } 132 133 // Returns the number of idle streams. IdleStreamSocketCount()134 size_t IdleStreamSocketCount() const { return idle_stream_sockets_.size(); } 135 136 // Returns the number of connecting streams. 137 size_t ConnectingStreamSocketCount() const; 138 139 // Returns the number of active streams. 140 size_t ActiveStreamSocketCount() const; 141 142 bool ReachedMaxStreamLimit() const; 143 144 // Returns the highest pending request priority if the group is stalled due to 145 // the per-pool limit, not the per-group limit. 146 std::optional<RequestPriority> GetPriorityIfStalledByPoolLimit() const; 147 148 // Closes all streams in this group and cancels all pending requests. 149 void FlushWithError(int error, 150 StreamCloseReason attempt_cancel_reason, 151 std::string_view net_log_close_reason_utf8); 152 153 // Increments the generation of this group. Closes idle streams. Streams 154 // handed out before this increment won't be reused. Cancels in-flight 155 // connection attempts. 156 void Refresh(std::string_view net_log_close_reason_utf8, 157 StreamCloseReason cancel_reason); 158 159 void CloseIdleStreams(std::string_view net_log_close_reason_utf8); 160 161 // Cancels all on-going jobs. 162 void CancelJobs(int error); 163 164 // Called when the server required HTTP/1.1. Clears the current SPDY session 165 // if exists. 166 void OnRequiredHttp11(); 167 168 // Called when the attempt manager has completed. 169 void OnAttemptManagerComplete(); 170 171 // Retrieves information on the current state of the group as a base::Value. 172 base::Value::Dict GetInfoAsValue() const; 173 174 void CleanupTimedoutIdleStreamSocketsForTesting(); 175 GetAttemptManagerForTesting()176 AttemptManager* GetAttemptManagerForTesting() const { 177 return attempt_manager_.get(); 178 } 179 180 private: 181 struct IdleStreamSocket { 182 IdleStreamSocket(std::unique_ptr<StreamSocket> stream_socket, 183 base::TimeTicks start_time); 184 ~IdleStreamSocket(); 185 186 IdleStreamSocket(const IdleStreamSocket&) = delete; 187 IdleStreamSocket& operator=(const IdleStreamSocket&) = delete; 188 189 std::unique_ptr<StreamSocket> stream_socket; 190 base::TimeTicks time_became_idle; 191 }; 192 193 enum class CleanupMode { 194 // Clean up only timed out idle streams. 195 kTimeoutOnly, 196 // Clean up all idle streams. 197 kForce, 198 }; 199 200 static base::expected<void, std::string_view> IsIdleStreamSocketUsable( 201 const IdleStreamSocket& idle); 202 203 void CleanupIdleStreamSockets(CleanupMode mode, 204 std::string_view net_log_close_reason_utf8); 205 206 void EnsureAttemptManager(); 207 208 // Returns true when `this` can be deleted. 209 bool CanComplete() const; 210 211 void MaybeComplete(); 212 213 const raw_ptr<HttpStreamPool> pool_; 214 const HttpStreamKey stream_key_; 215 const SpdySessionKey spdy_session_key_; 216 const QuicSessionAliasKey quic_session_alias_key_; 217 const NetLogWithSource net_log_; 218 const bool force_quic_; 219 220 size_t handed_out_stream_count_ = 0; 221 int64_t generation_ = 0; 222 std::list<IdleStreamSocket> idle_stream_sockets_; 223 224 std::unique_ptr<AttemptManager> attempt_manager_; 225 226 base::WeakPtrFactory<Group> weak_ptr_factory_{this}; 227 }; 228 229 } // namespace net 230 231 #endif // NET_HTTP_HTTP_STREAM_POOL_GROUP_H_ 232