blob: 379f097abc4b7d04baad260eb04835313d653e41 [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.
105 bool WaitForCryptoHandshakeConfirmed() QUIC_MUST_USE_RESULT;
106
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
130 void SetUserAgentID(const QuicString& user_agent_id) {
131 crypto_config_.set_user_agent_id(user_agent_id);
132 }
133
134 // SetChannelIDSource sets a ChannelIDSource that will be called, when the
135 // server supports channel IDs, to obtain a channel ID for signing a message
136 // proving possession of the channel ID. This object takes ownership of
137 // |source|.
138 void SetChannelIDSource(ChannelIDSource* source) {
139 crypto_config_.SetChannelIDSource(source);
140 }
141
142 const ParsedQuicVersionVector& supported_versions() const {
143 return supported_versions_;
144 }
145
146 void SetSupportedVersions(const ParsedQuicVersionVector& versions) {
147 supported_versions_ = versions;
148 }
149
150 QuicConfig* config() { return &config_; }
151
152 QuicCryptoClientConfig* crypto_config() { return &crypto_config_; }
153
154 // Change the initial maximum packet size of the connection. Has to be called
155 // before Connect()/StartConnect() in order to have any effect.
156 void set_initial_max_packet_length(QuicByteCount initial_max_packet_length) {
157 initial_max_packet_length_ = initial_max_packet_length;
158 }
159
160 int num_stateless_rejects_received() const {
161 return num_stateless_rejects_received_;
162 }
163
164 // The number of client hellos sent, taking stateless rejects into
165 // account. In the case of a stateless reject, the initial
166 // connection object may be torn down and a new one created. The
167 // user cannot rely upon the latest connection object to get the
168 // total number of client hellos sent, and should use this function
169 // instead.
170 int GetNumSentClientHellos();
171
172 // Gather the stats for the last session and update the stats for the overall
173 // connection.
174 void UpdateStats();
175
176 // The number of server config updates received. We assume no
177 // updates can be sent during a previously, statelessly rejected
178 // connection, so only the latest session is taken into account.
179 int GetNumReceivedServerConfigUpdates();
180
181 // Returns any errors that occurred at the connection-level (as
182 // opposed to the session-level). When a stateless reject occurs,
183 // the error of the last session may not reflect the overall state
184 // of the connection.
185 QuicErrorCode connection_error() const;
186 void set_connection_error(QuicErrorCode connection_error) {
187 connection_error_ = connection_error;
188 }
189
190 bool connected_or_attempting_connect() const {
191 return connected_or_attempting_connect_;
192 }
193 void set_connected_or_attempting_connect(
194 bool connected_or_attempting_connect) {
195 connected_or_attempting_connect_ = connected_or_attempting_connect;
196 }
197
198 QuicPacketWriter* writer() { return writer_.get(); }
199 void set_writer(QuicPacketWriter* writer) {
200 if (writer_.get() != writer) {
201 writer_.reset(writer);
202 }
203 }
204
205 void reset_writer() { writer_.reset(); }
206
207 ProofVerifier* proof_verifier() const;
208
209 void set_bind_to_address(QuicIpAddress address) {
210 bind_to_address_ = address;
211 }
212
213 QuicIpAddress bind_to_address() const { return bind_to_address_; }
214
215 void set_local_port(int local_port) { local_port_ = local_port; }
216
217 int local_port() const { return local_port_; }
218
219 const QuicSocketAddress& server_address() const { return server_address_; }
220
221 void set_server_address(const QuicSocketAddress& server_address) {
222 server_address_ = server_address;
223 }
224
225 QuicConnectionHelperInterface* helper() { return helper_.get(); }
226
227 NetworkHelper* network_helper();
228 const NetworkHelper* network_helper() const;
229
230 bool initialized() const { return initialized_; }
231
232 void SetPreSharedKey(QuicStringPiece key) {
233 crypto_config_.set_pre_shared_key(key);
234 }
235
236 protected:
237 // TODO(rch): Move GetNumSentClientHellosFromSession and
238 // GetNumReceivedServerConfigUpdatesFromSession into a new/better
239 // QuicSpdyClientSession class. The current inherits dependencies from
240 // Spdy. When that happens this class and all its subclasses should
241 // work with QuicSpdyClientSession instead of QuicSession.
242 // That will obviate the need for the pure virtual functions below.
243
244 // Extract the number of sent client hellos from the session.
245 virtual int GetNumSentClientHellosFromSession() = 0;
246
247 // The number of server config updates received. We assume no
248 // updates can be sent during a previously, statelessly rejected
249 // connection, so only the latest session is taken into account.
250 virtual int GetNumReceivedServerConfigUpdatesFromSession() = 0;
251
252 // If this client supports buffering data, resend it.
253 virtual void ResendSavedData() = 0;
254
255 // If this client supports buffering data, clear it.
256 virtual void ClearDataToResend() = 0;
257
258 // Takes ownership of |connection|. If you override this function,
259 // you probably want to call ResetSession() in your destructor.
260 // TODO(rch): Change the connection parameter to take in a
261 // std::unique_ptr<QuicConnection> instead.
262 virtual std::unique_ptr<QuicSession> CreateQuicClientSession(
263 const ParsedQuicVersionVector& supported_versions,
264 QuicConnection* connection) = 0;
265
266 // Generates the next ConnectionId for |server_id_|. By default, if the
267 // cached server config contains a server-designated ID, that ID will be
268 // returned. Otherwise, the next random ID will be returned.
269 QuicConnectionId GetNextConnectionId();
270
271 // Returns the next server-designated ConnectionId from the cached config for
272 // |server_id_|, if it exists. Otherwise, returns 0.
273 QuicConnectionId GetNextServerDesignatedConnectionId();
274
275 // Generates a new, random connection ID (as opposed to a server-designated
276 // connection ID).
277 virtual QuicConnectionId GenerateNewConnectionId();
278
279 QuicAlarmFactory* alarm_factory() { return alarm_factory_.get(); }
280
281 // Subclasses may need to explicitly clear the session on destruction
282 // if they create it with objects that will be destroyed before this is.
283 // You probably want to call this if you override CreateQuicSpdyClientSession.
284 void ResetSession() { session_.reset(); }
285
286 private:
287 // Returns true and set |version| if client can reconnect with a different
288 // version.
289 bool CanReconnectWithDifferentVersion(ParsedQuicVersion* version) const;
290
291 // |server_id_| is a tuple (hostname, port, is_https) of the server.
292 QuicServerId server_id_;
293
294 // Tracks if the client is initialized to connect.
295 bool initialized_;
296
297 // Address of the server.
298 QuicSocketAddress server_address_;
299
300 // If initialized, the address to bind to.
301 QuicIpAddress bind_to_address_;
302
303 // Local port to bind to. Initialize to 0.
304 int local_port_;
305
306 // config_ and crypto_config_ contain configuration and cached state about
307 // servers.
308 QuicConfig config_;
309 QuicCryptoClientConfig crypto_config_;
310
311 // Helper to be used by created connections. Must outlive |session_|.
312 std::unique_ptr<QuicConnectionHelperInterface> helper_;
313
314 // Alarm factory to be used by created connections. Must outlive |session_|.
315 std::unique_ptr<QuicAlarmFactory> alarm_factory_;
316
317 // Writer used to actually send packets to the wire. Must outlive |session_|.
318 std::unique_ptr<QuicPacketWriter> writer_;
319
320 // Session which manages streams.
321 std::unique_ptr<QuicSession> session_;
322
323 // This vector contains QUIC versions which we currently support.
324 // This should be ordered such that the highest supported version is the first
325 // element, with subsequent elements in descending order (versions can be
326 // skipped as necessary). We will always pick supported_versions_[0] as the
327 // initial version to use.
328 ParsedQuicVersionVector supported_versions_;
329
330 // The initial value of maximum packet size of the connection. If set to
331 // zero, the default is used.
332 QuicByteCount initial_max_packet_length_;
333
334 // The number of stateless rejects received during the current/latest
335 // connection.
336 // TODO(jokulik): Consider some consistent naming scheme (or other) for member
337 // variables that are kept per-request, per-connection, and over the client's
338 // lifetime.
339 int num_stateless_rejects_received_;
340
341 // The number of hellos sent during the current/latest connection.
342 int num_sent_client_hellos_;
343
344 // Used to store any errors that occurred with the overall connection (as
345 // opposed to that associated with the last session object).
346 QuicErrorCode connection_error_;
347
348 // True when the client is attempting to connect or re-connect the session (in
349 // the case of a stateless reject). Set to false between a call to
350 // Disconnect() and the subsequent call to StartConnect(). When
351 // connected_or_attempting_connect_ is false, the session object corresponds
352 // to the previous client-level connection.
353 bool connected_or_attempting_connect_;
354
355 // The network helper used to create sockets and manage the event loop.
356 // Not owned by this class.
357 std::unique_ptr<NetworkHelper> network_helper_;
358};
359
360} // namespace quic
361
362#endif // QUICHE_QUIC_TOOLS_QUIC_CLIENT_BASE_H_