blob: fb15b862b081484aeab44dabdda465c6204497e9 [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
wub4b1a5e62019-06-06 12:20:05 -0700152 // The number of client hellos sent.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500153 int GetNumSentClientHellos();
154
155 // Gather the stats for the last session and update the stats for the overall
156 // connection.
157 void UpdateStats();
158
wub4b1a5e62019-06-06 12:20:05 -0700159 // The number of server config updates received.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500160 int GetNumReceivedServerConfigUpdates();
161
wub4b1a5e62019-06-06 12:20:05 -0700162 // Returns any errors that occurred at the connection-level.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500163 QuicErrorCode connection_error() const;
164 void set_connection_error(QuicErrorCode connection_error) {
165 connection_error_ = connection_error;
166 }
167
168 bool connected_or_attempting_connect() const {
169 return connected_or_attempting_connect_;
170 }
171 void set_connected_or_attempting_connect(
172 bool connected_or_attempting_connect) {
173 connected_or_attempting_connect_ = connected_or_attempting_connect;
174 }
175
176 QuicPacketWriter* writer() { return writer_.get(); }
177 void set_writer(QuicPacketWriter* writer) {
178 if (writer_.get() != writer) {
179 writer_.reset(writer);
180 }
181 }
182
183 void reset_writer() { writer_.reset(); }
184
185 ProofVerifier* proof_verifier() const;
186
187 void set_bind_to_address(QuicIpAddress address) {
188 bind_to_address_ = address;
189 }
190
191 QuicIpAddress bind_to_address() const { return bind_to_address_; }
192
193 void set_local_port(int local_port) { local_port_ = local_port; }
194
195 int local_port() const { return local_port_; }
196
197 const QuicSocketAddress& server_address() const { return server_address_; }
198
199 void set_server_address(const QuicSocketAddress& server_address) {
200 server_address_ = server_address;
201 }
202
203 QuicConnectionHelperInterface* helper() { return helper_.get(); }
204
205 NetworkHelper* network_helper();
206 const NetworkHelper* network_helper() const;
207
208 bool initialized() const { return initialized_; }
209
210 void SetPreSharedKey(QuicStringPiece key) {
211 crypto_config_.set_pre_shared_key(key);
212 }
213
214 protected:
215 // TODO(rch): Move GetNumSentClientHellosFromSession and
216 // GetNumReceivedServerConfigUpdatesFromSession into a new/better
217 // QuicSpdyClientSession class. The current inherits dependencies from
218 // Spdy. When that happens this class and all its subclasses should
219 // work with QuicSpdyClientSession instead of QuicSession.
220 // That will obviate the need for the pure virtual functions below.
221
222 // Extract the number of sent client hellos from the session.
223 virtual int GetNumSentClientHellosFromSession() = 0;
224
wub4b1a5e62019-06-06 12:20:05 -0700225 // The number of server config updates received.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500226 virtual int GetNumReceivedServerConfigUpdatesFromSession() = 0;
227
228 // If this client supports buffering data, resend it.
229 virtual void ResendSavedData() = 0;
230
231 // If this client supports buffering data, clear it.
232 virtual void ClearDataToResend() = 0;
233
234 // Takes ownership of |connection|. If you override this function,
235 // you probably want to call ResetSession() in your destructor.
236 // TODO(rch): Change the connection parameter to take in a
237 // std::unique_ptr<QuicConnection> instead.
238 virtual std::unique_ptr<QuicSession> CreateQuicClientSession(
239 const ParsedQuicVersionVector& supported_versions,
240 QuicConnection* connection) = 0;
241
242 // Generates the next ConnectionId for |server_id_|. By default, if the
243 // cached server config contains a server-designated ID, that ID will be
244 // returned. Otherwise, the next random ID will be returned.
245 QuicConnectionId GetNextConnectionId();
246
247 // Returns the next server-designated ConnectionId from the cached config for
248 // |server_id_|, if it exists. Otherwise, returns 0.
249 QuicConnectionId GetNextServerDesignatedConnectionId();
250
251 // Generates a new, random connection ID (as opposed to a server-designated
252 // connection ID).
253 virtual QuicConnectionId GenerateNewConnectionId();
254
dschinazi346b7ce2019-06-05 01:38:18 -0700255 // Returns the client connection ID to use.
256 virtual QuicConnectionId GetClientConnectionId();
257
QUICHE teama6ef0a62019-03-07 20:34:33 -0500258 QuicAlarmFactory* alarm_factory() { return alarm_factory_.get(); }
259
260 // Subclasses may need to explicitly clear the session on destruction
261 // if they create it with objects that will be destroyed before this is.
262 // You probably want to call this if you override CreateQuicSpdyClientSession.
263 void ResetSession() { session_.reset(); }
264
QUICHE teamc2653c42019-03-08 13:30:06 -0800265 // Returns true if the corresponding of this client has active requests.
266 virtual bool HasActiveRequests() = 0;
267
QUICHE teama6ef0a62019-03-07 20:34:33 -0500268 private:
269 // Returns true and set |version| if client can reconnect with a different
270 // version.
271 bool CanReconnectWithDifferentVersion(ParsedQuicVersion* version) const;
272
273 // |server_id_| is a tuple (hostname, port, is_https) of the server.
274 QuicServerId server_id_;
275
276 // Tracks if the client is initialized to connect.
277 bool initialized_;
278
279 // Address of the server.
280 QuicSocketAddress server_address_;
281
282 // If initialized, the address to bind to.
283 QuicIpAddress bind_to_address_;
284
285 // Local port to bind to. Initialize to 0.
286 int local_port_;
287
288 // config_ and crypto_config_ contain configuration and cached state about
289 // servers.
290 QuicConfig config_;
291 QuicCryptoClientConfig crypto_config_;
292
293 // Helper to be used by created connections. Must outlive |session_|.
294 std::unique_ptr<QuicConnectionHelperInterface> helper_;
295
296 // Alarm factory to be used by created connections. Must outlive |session_|.
297 std::unique_ptr<QuicAlarmFactory> alarm_factory_;
298
299 // Writer used to actually send packets to the wire. Must outlive |session_|.
300 std::unique_ptr<QuicPacketWriter> writer_;
301
302 // Session which manages streams.
303 std::unique_ptr<QuicSession> session_;
304
305 // This vector contains QUIC versions which we currently support.
306 // This should be ordered such that the highest supported version is the first
307 // element, with subsequent elements in descending order (versions can be
308 // skipped as necessary). We will always pick supported_versions_[0] as the
309 // initial version to use.
310 ParsedQuicVersionVector supported_versions_;
311
312 // The initial value of maximum packet size of the connection. If set to
313 // zero, the default is used.
314 QuicByteCount initial_max_packet_length_;
315
QUICHE teama6ef0a62019-03-07 20:34:33 -0500316 // The number of hellos sent during the current/latest connection.
317 int num_sent_client_hellos_;
318
319 // Used to store any errors that occurred with the overall connection (as
320 // opposed to that associated with the last session object).
321 QuicErrorCode connection_error_;
322
wub4b1a5e62019-06-06 12:20:05 -0700323 // True when the client is attempting to connect. Set to false between a call
324 // to Disconnect() and the subsequent call to StartConnect(). When
QUICHE teama6ef0a62019-03-07 20:34:33 -0500325 // connected_or_attempting_connect_ is false, the session object corresponds
326 // to the previous client-level connection.
327 bool connected_or_attempting_connect_;
328
329 // The network helper used to create sockets and manage the event loop.
330 // Not owned by this class.
331 std::unique_ptr<NetworkHelper> network_helper_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500332};
333
334} // namespace quic
335
336#endif // QUICHE_QUIC_TOOLS_QUIC_CLIENT_BASE_H_