• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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