blob: 134404be1f3493c31ce782d5729fdfb54b18c5d2 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2015 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
5// A base class for the toy client, which connects to a specified port and sends
6// QUIC request to that endpoint.
7
8#ifndef QUICHE_QUIC_TOOLS_QUIC_CLIENT_BASE_H_
9#define QUICHE_QUIC_TOOLS_QUIC_CLIENT_BASE_H_
10
11#include <string>
12
13#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
14#include "net/third_party/quiche/src/quic/core/http/quic_client_push_promise_index.h"
15#include "net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.h"
16#include "net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.h"
17#include "net/third_party/quiche/src/quic/core/quic_config.h"
18#include "net/third_party/quiche/src/quic/platform/api/quic_macros.h"
19#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
20#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
21
22namespace quic {
23
24class ProofVerifier;
25class QuicServerId;
26
27// QuicClientBase handles establishing a connection to the passed in
28// server id, including ensuring that it supports the passed in versions
29// and config.
30// Subclasses derived from this class are responsible for creating the
31// actual QuicSession instance, as well as defining functions that
32// create and run the underlying network transport.
33class QuicClientBase {
34 public:
35 // An interface to various network events that the QuicClient will need to
36 // interact with.
37 class NetworkHelper {
38 public:
39 virtual ~NetworkHelper();
40
41 // Runs one iteration of the event loop.
42 virtual void RunEventLoop() = 0;
43
44 // Used during initialization: creates the UDP socket FD, sets socket
45 // options, and binds the socket to our address.
46 virtual bool CreateUDPSocketAndBind(QuicSocketAddress server_address,
47 QuicIpAddress bind_to_address,
48 int bind_to_port) = 0;
49
50 // Unregister and close all open UDP sockets.
51 virtual void CleanUpAllUDPSockets() = 0;
52
53 // If the client has at least one UDP socket, return address of the latest
54 // created one. Otherwise, return an empty socket address.
55 virtual QuicSocketAddress GetLatestClientAddress() const = 0;
56
57 // Creates a packet writer to be used for the next connection.
58 virtual QuicPacketWriter* CreateQuicPacketWriter() = 0;
59 };
60
61 QuicClientBase(const QuicServerId& server_id,
62 const ParsedQuicVersionVector& supported_versions,
63 const QuicConfig& config,
64 QuicConnectionHelperInterface* helper,
65 QuicAlarmFactory* alarm_factory,
66 std::unique_ptr<NetworkHelper> network_helper,
67 std::unique_ptr<ProofVerifier> proof_verifier);
68 QuicClientBase(const QuicClientBase&) = delete;
69 QuicClientBase& operator=(const QuicClientBase&) = delete;
70
71 virtual ~QuicClientBase();
72
73 // Initializes the client to create a connection. Should be called exactly
74 // once before calling StartConnect or Connect. Returns true if the
75 // initialization succeeds, false otherwise.
76 virtual bool Initialize();
77
78 // "Connect" to the QUIC server, including performing synchronous crypto
79 // handshake.
80 bool Connect();
81
82 // Start the crypto handshake. This can be done in place of the synchronous
83 // Connect(), but callers are responsible for making sure the crypto handshake
84 // completes.
85 void StartConnect();
86
87 // Calls session()->Initialize(). Subclasses may override this if any extra
88 // initialization needs to be done. Subclasses should expect that session()
89 // is non-null and valid.
90 virtual void InitializeSession();
91
92 // Disconnects from the QUIC server.
93 void Disconnect();
94
95 // Returns true if the crypto handshake has yet to establish encryption.
96 // Returns false if encryption is active (even if the server hasn't confirmed
97 // the handshake) or if the connection has been closed.
98 bool EncryptionBeingEstablished();
99
100 // Wait for events until the stream with the given ID is closed.
101 void WaitForStreamToClose(QuicStreamId id);
102
103 // Wait for events until the handshake is confirmed.
104 // Returns true if the crypto handshake succeeds, false otherwise.
danzh711bd182019-05-01 13:44:19 -0700105 QUIC_MUST_USE_RESULT bool WaitForCryptoHandshakeConfirmed();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500106
107 // Wait up to 50ms, and handle any events which occur.
108 // Returns true if there are any outstanding requests.
109 bool WaitForEvents();
110
111 // Migrate to a new socket (new_host) during an active connection.
112 bool MigrateSocket(const QuicIpAddress& new_host);
113
114 // Migrate to a new socket (new_host, port) during an active connection.
115 bool MigrateSocketWithSpecifiedPort(const QuicIpAddress& new_host, int port);
116
117 // Open a new socket to change to a new ephemeral port.
118 bool ChangeEphemeralPort();
119
120 QuicSession* session();
121
122 bool connected() const;
123 bool goaway_received() const;
124
125 const QuicServerId& server_id() const { return server_id_; }
126
127 // This should only be set before the initial Connect()
128 void set_server_id(const QuicServerId& server_id) { server_id_ = server_id; }
129
vasilvvc48c8712019-03-11 13:38:16 -0700130 void SetUserAgentID(const std::string& user_agent_id) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500131 crypto_config_.set_user_agent_id(user_agent_id);
132 }
133
QUICHE teama6ef0a62019-03-07 20:34:33 -0500134 const ParsedQuicVersionVector& supported_versions() const {
135 return supported_versions_;
136 }
137
138 void SetSupportedVersions(const ParsedQuicVersionVector& versions) {
139 supported_versions_ = versions;
140 }
141
142 QuicConfig* config() { return &config_; }
143
144 QuicCryptoClientConfig* crypto_config() { return &crypto_config_; }
145
146 // Change the initial maximum packet size of the connection. Has to be called
147 // before Connect()/StartConnect() in order to have any effect.
148 void set_initial_max_packet_length(QuicByteCount initial_max_packet_length) {
149 initial_max_packet_length_ = initial_max_packet_length;
150 }
151
152 int num_stateless_rejects_received() const {
153 return num_stateless_rejects_received_;
154 }
155
156 // The number of client hellos sent, taking stateless rejects into
157 // account. In the case of a stateless reject, the initial
158 // connection object may be torn down and a new one created. The
159 // user cannot rely upon the latest connection object to get the
160 // total number of client hellos sent, and should use this function
161 // instead.
162 int GetNumSentClientHellos();
163
164 // Gather the stats for the last session and update the stats for the overall
165 // connection.
166 void UpdateStats();
167
168 // The number of server config updates received. We assume no
169 // updates can be sent during a previously, statelessly rejected
170 // connection, so only the latest session is taken into account.
171 int GetNumReceivedServerConfigUpdates();
172
173 // Returns any errors that occurred at the connection-level (as
174 // opposed to the session-level). When a stateless reject occurs,
175 // the error of the last session may not reflect the overall state
176 // of the connection.
177 QuicErrorCode connection_error() const;
178 void set_connection_error(QuicErrorCode connection_error) {
179 connection_error_ = connection_error;
180 }
181
182 bool connected_or_attempting_connect() const {
183 return connected_or_attempting_connect_;
184 }
185 void set_connected_or_attempting_connect(
186 bool connected_or_attempting_connect) {
187 connected_or_attempting_connect_ = connected_or_attempting_connect;
188 }
189
190 QuicPacketWriter* writer() { return writer_.get(); }
191 void set_writer(QuicPacketWriter* writer) {
192 if (writer_.get() != writer) {
193 writer_.reset(writer);
194 }
195 }
196
197 void reset_writer() { writer_.reset(); }
198
199 ProofVerifier* proof_verifier() const;
200
201 void set_bind_to_address(QuicIpAddress address) {
202 bind_to_address_ = address;
203 }
204
205 QuicIpAddress bind_to_address() const { return bind_to_address_; }
206
207 void set_local_port(int local_port) { local_port_ = local_port; }
208
209 int local_port() const { return local_port_; }
210
211 const QuicSocketAddress& server_address() const { return server_address_; }
212
213 void set_server_address(const QuicSocketAddress& server_address) {
214 server_address_ = server_address;
215 }
216
217 QuicConnectionHelperInterface* helper() { return helper_.get(); }
218
219 NetworkHelper* network_helper();
220 const NetworkHelper* network_helper() const;
221
222 bool initialized() const { return initialized_; }
223
224 void SetPreSharedKey(QuicStringPiece key) {
225 crypto_config_.set_pre_shared_key(key);
226 }
227
228 protected:
229 // TODO(rch): Move GetNumSentClientHellosFromSession and
230 // GetNumReceivedServerConfigUpdatesFromSession into a new/better
231 // QuicSpdyClientSession class. The current inherits dependencies from
232 // Spdy. When that happens this class and all its subclasses should
233 // work with QuicSpdyClientSession instead of QuicSession.
234 // That will obviate the need for the pure virtual functions below.
235
236 // Extract the number of sent client hellos from the session.
237 virtual int GetNumSentClientHellosFromSession() = 0;
238
239 // The number of server config updates received. We assume no
240 // updates can be sent during a previously, statelessly rejected
241 // connection, so only the latest session is taken into account.
242 virtual int GetNumReceivedServerConfigUpdatesFromSession() = 0;
243
244 // If this client supports buffering data, resend it.
245 virtual void ResendSavedData() = 0;
246
247 // If this client supports buffering data, clear it.
248 virtual void ClearDataToResend() = 0;
249
250 // Takes ownership of |connection|. If you override this function,
251 // you probably want to call ResetSession() in your destructor.
252 // TODO(rch): Change the connection parameter to take in a
253 // std::unique_ptr<QuicConnection> instead.
254 virtual std::unique_ptr<QuicSession> CreateQuicClientSession(
255 const ParsedQuicVersionVector& supported_versions,
256 QuicConnection* connection) = 0;
257
258 // Generates the next ConnectionId for |server_id_|. By default, if the
259 // cached server config contains a server-designated ID, that ID will be
260 // returned. Otherwise, the next random ID will be returned.
261 QuicConnectionId GetNextConnectionId();
262
263 // Returns the next server-designated ConnectionId from the cached config for
264 // |server_id_|, if it exists. Otherwise, returns 0.
265 QuicConnectionId GetNextServerDesignatedConnectionId();
266
267 // Generates a new, random connection ID (as opposed to a server-designated
268 // connection ID).
269 virtual QuicConnectionId GenerateNewConnectionId();
270
dschinazi346b7ce2019-06-05 01:38:18 -0700271 // Returns the client connection ID to use.
272 virtual QuicConnectionId GetClientConnectionId();
273
QUICHE teama6ef0a62019-03-07 20:34:33 -0500274 QuicAlarmFactory* alarm_factory() { return alarm_factory_.get(); }
275
276 // Subclasses may need to explicitly clear the session on destruction
277 // if they create it with objects that will be destroyed before this is.
278 // You probably want to call this if you override CreateQuicSpdyClientSession.
279 void ResetSession() { session_.reset(); }
280
QUICHE teamc2653c42019-03-08 13:30:06 -0800281 // Returns true if the corresponding of this client has active requests.
282 virtual bool HasActiveRequests() = 0;
283
QUICHE teama6ef0a62019-03-07 20:34:33 -0500284 private:
285 // Returns true and set |version| if client can reconnect with a different
286 // version.
287 bool CanReconnectWithDifferentVersion(ParsedQuicVersion* version) const;
288
289 // |server_id_| is a tuple (hostname, port, is_https) of the server.
290 QuicServerId server_id_;
291
292 // Tracks if the client is initialized to connect.
293 bool initialized_;
294
295 // Address of the server.
296 QuicSocketAddress server_address_;
297
298 // If initialized, the address to bind to.
299 QuicIpAddress bind_to_address_;
300
301 // Local port to bind to. Initialize to 0.
302 int local_port_;
303
304 // config_ and crypto_config_ contain configuration and cached state about
305 // servers.
306 QuicConfig config_;
307 QuicCryptoClientConfig crypto_config_;
308
309 // Helper to be used by created connections. Must outlive |session_|.
310 std::unique_ptr<QuicConnectionHelperInterface> helper_;
311
312 // Alarm factory to be used by created connections. Must outlive |session_|.
313 std::unique_ptr<QuicAlarmFactory> alarm_factory_;
314
315 // Writer used to actually send packets to the wire. Must outlive |session_|.
316 std::unique_ptr<QuicPacketWriter> writer_;
317
318 // Session which manages streams.
319 std::unique_ptr<QuicSession> session_;
320
321 // This vector contains QUIC versions which we currently support.
322 // This should be ordered such that the highest supported version is the first
323 // element, with subsequent elements in descending order (versions can be
324 // skipped as necessary). We will always pick supported_versions_[0] as the
325 // initial version to use.
326 ParsedQuicVersionVector supported_versions_;
327
328 // The initial value of maximum packet size of the connection. If set to
329 // zero, the default is used.
330 QuicByteCount initial_max_packet_length_;
331
332 // The number of stateless rejects received during the current/latest
333 // connection.
334 // TODO(jokulik): Consider some consistent naming scheme (or other) for member
335 // variables that are kept per-request, per-connection, and over the client's
336 // lifetime.
337 int num_stateless_rejects_received_;
338
339 // The number of hellos sent during the current/latest connection.
340 int num_sent_client_hellos_;
341
342 // Used to store any errors that occurred with the overall connection (as
343 // opposed to that associated with the last session object).
344 QuicErrorCode connection_error_;
345
346 // True when the client is attempting to connect or re-connect the session (in
347 // the case of a stateless reject). Set to false between a call to
348 // Disconnect() and the subsequent call to StartConnect(). When
349 // connected_or_attempting_connect_ is false, the session object corresponds
350 // to the previous client-level connection.
351 bool connected_or_attempting_connect_;
352
353 // The network helper used to create sockets and manage the event loop.
354 // Not owned by this class.
355 std::unique_ptr<NetworkHelper> network_helper_;
356};
357
358} // namespace quic
359
360#endif // QUICHE_QUIC_TOOLS_QUIC_CLIENT_BASE_H_