OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/tools/quic/quic_simple_client.h" | 5 #include "net/tools/quic/quic_simple_client.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/run_loop.h" | 8 #include "base/run_loop.h" |
9 #include "base/thread_task_runner_handle.h" | 9 #include "base/thread_task_runner_handle.h" |
10 #include "net/base/net_errors.h" | 10 #include "net/base/net_errors.h" |
11 #include "net/http/http_request_info.h" | 11 #include "net/http/http_request_info.h" |
12 #include "net/http/http_response_info.h" | 12 #include "net/http/http_response_info.h" |
13 #include "net/quic/crypto/quic_random.h" | 13 #include "net/quic/crypto/quic_random.h" |
14 #include "net/quic/quic_connection.h" | 14 #include "net/quic/quic_connection.h" |
15 #include "net/quic/quic_connection_helper.h" | 15 #include "net/quic/quic_connection_helper.h" |
16 #include "net/quic/quic_crypto_client_stream.h" | |
17 #include "net/quic/quic_default_packet_writer.h" | 16 #include "net/quic/quic_default_packet_writer.h" |
18 #include "net/quic/quic_flags.h" | 17 #include "net/quic/quic_flags.h" |
19 #include "net/quic/quic_protocol.h" | 18 #include "net/quic/quic_protocol.h" |
20 #include "net/quic/quic_server_id.h" | 19 #include "net/quic/quic_server_id.h" |
21 #include "net/quic/spdy_utils.h" | 20 #include "net/quic/spdy_utils.h" |
22 #include "net/spdy/spdy_http_utils.h" | 21 #include "net/spdy/spdy_http_utils.h" |
23 #include "net/udp/udp_client_socket.h" | 22 #include "net/udp/udp_client_socket.h" |
24 | 23 |
25 using std::string; | 24 using std::string; |
26 using std::vector; | 25 using std::vector; |
27 | 26 |
28 namespace net { | 27 namespace net { |
29 namespace tools { | 28 namespace tools { |
30 | 29 |
31 void QuicSimpleClient::ClientQuicDataToResend::Resend() { | 30 void QuicSimpleClient::ClientQuicDataToResend::Resend() { |
32 client_->SendRequest(*headers_, body_, fin_); | 31 client_->SendRequest(*headers_, body_, fin_); |
33 delete headers_; | 32 delete headers_; |
34 headers_ = nullptr; | 33 headers_ = nullptr; |
35 } | 34 } |
36 | 35 |
37 QuicSimpleClient::QuicSimpleClient(IPEndPoint server_address, | 36 QuicSimpleClient::QuicSimpleClient(IPEndPoint server_address, |
38 const QuicServerId& server_id, | 37 const QuicServerId& server_id, |
39 const QuicVersionVector& supported_versions) | 38 const QuicVersionVector& supported_versions) |
40 : server_address_(server_address), | 39 : QuicClientBase(server_id, supported_versions, QuicConfig()), |
41 server_id_(server_id), | 40 server_address_(server_address), |
42 local_port_(0), | 41 local_port_(0), |
43 helper_(CreateQuicConnectionHelper()), | 42 helper_(CreateQuicConnectionHelper()), |
44 initialized_(false), | 43 initialized_(false), |
45 supported_versions_(supported_versions), | |
46 packet_reader_started_(false), | 44 packet_reader_started_(false), |
47 weak_factory_(this) {} | 45 weak_factory_(this) {} |
48 | 46 |
49 QuicSimpleClient::QuicSimpleClient(IPEndPoint server_address, | 47 QuicSimpleClient::QuicSimpleClient(IPEndPoint server_address, |
50 const QuicServerId& server_id, | 48 const QuicServerId& server_id, |
51 const QuicVersionVector& supported_versions, | 49 const QuicVersionVector& supported_versions, |
52 const QuicConfig& config) | 50 const QuicConfig& config) |
53 : server_address_(server_address), | 51 : QuicClientBase(server_id, supported_versions, config), |
54 server_id_(server_id), | 52 server_address_(server_address), |
55 config_(config), | |
56 local_port_(0), | 53 local_port_(0), |
57 helper_(CreateQuicConnectionHelper()), | 54 helper_(CreateQuicConnectionHelper()), |
58 initialized_(false), | 55 initialized_(false), |
59 supported_versions_(supported_versions), | |
60 initial_max_packet_length_(0), | |
61 num_stateless_rejects_received_(0), | |
62 num_sent_client_hellos_(0), | |
63 connection_error_(QUIC_NO_ERROR), | |
64 connected_or_attempting_connect_(false), | |
65 packet_reader_started_(false), | 56 packet_reader_started_(false), |
66 weak_factory_(this) {} | 57 weak_factory_(this) {} |
67 | 58 |
68 QuicSimpleClient::~QuicSimpleClient() { | 59 QuicSimpleClient::~QuicSimpleClient() { |
69 if (connected()) { | 60 if (connected()) { |
70 session()->connection()->SendConnectionClosePacket( | 61 session()->connection()->SendConnectionClosePacket( |
71 QUIC_PEER_GOING_AWAY, ""); | 62 QUIC_PEER_GOING_AWAY, ""); |
72 } | 63 } |
73 STLDeleteElements(&data_to_resend_on_connect_); | 64 STLDeleteElements(&data_to_resend_on_connect_); |
74 STLDeleteElements(&data_sent_before_handshake_); | 65 STLDeleteElements(&data_sent_before_handshake_); |
75 } | 66 } |
76 | 67 |
77 bool QuicSimpleClient::Initialize() { | 68 bool QuicSimpleClient::Initialize() { |
78 DCHECK(!initialized_); | 69 DCHECK(!initialized_); |
79 | 70 |
80 num_sent_client_hellos_ = 0; | 71 QuicClientBase::Initialize(); |
81 num_stateless_rejects_received_ = 0; | |
82 connection_error_ = QUIC_NO_ERROR; | |
83 connected_or_attempting_connect_ = false; | |
84 | 72 |
85 if (!CreateUDPSocket()) { | 73 if (!CreateUDPSocket()) { |
86 return false; | 74 return false; |
87 } | 75 } |
88 | 76 |
89 initialized_ = true; | 77 initialized_ = true; |
90 return true; | 78 return true; |
91 } | 79 } |
92 | 80 |
93 QuicSimpleClient::DummyPacketWriterFactory::DummyPacketWriterFactory( | |
94 QuicPacketWriter* writer) | |
95 : writer_(writer) {} | |
96 | |
97 QuicSimpleClient::DummyPacketWriterFactory::~DummyPacketWriterFactory() {} | |
98 | |
99 QuicPacketWriter* QuicSimpleClient::DummyPacketWriterFactory::Create( | |
100 QuicConnection* /*connection*/) const { | |
101 return writer_; | |
102 } | |
103 | |
104 QuicSimpleClient::QuicDataToResend::QuicDataToResend(HttpRequestInfo* headers, | 81 QuicSimpleClient::QuicDataToResend::QuicDataToResend(HttpRequestInfo* headers, |
105 StringPiece body, | 82 StringPiece body, |
106 bool fin) | 83 bool fin) |
107 : headers_(headers), body_(body), fin_(fin) {} | 84 : headers_(headers), body_(body), fin_(fin) {} |
108 | 85 |
109 QuicSimpleClient::QuicDataToResend::~QuicDataToResend() { | 86 QuicSimpleClient::QuicDataToResend::~QuicDataToResend() { |
110 if (headers_) { | 87 if (headers_) { |
111 delete headers_; | 88 delete headers_; |
112 } | 89 } |
113 } | 90 } |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 } | 163 } |
187 if (FLAGS_enable_quic_stateless_reject_support && connected() && | 164 if (FLAGS_enable_quic_stateless_reject_support && connected() && |
188 !data_to_resend_on_connect_.empty()) { | 165 !data_to_resend_on_connect_.empty()) { |
189 // A connection has been established and there was previously queued data | 166 // A connection has been established and there was previously queued data |
190 // to resend. Resend it and empty the queue. | 167 // to resend. Resend it and empty the queue. |
191 for (QuicDataToResend* data : data_to_resend_on_connect_) { | 168 for (QuicDataToResend* data : data_to_resend_on_connect_) { |
192 data->Resend(); | 169 data->Resend(); |
193 } | 170 } |
194 STLDeleteElements(&data_to_resend_on_connect_); | 171 STLDeleteElements(&data_to_resend_on_connect_); |
195 } | 172 } |
196 if (session_.get() != nullptr && | 173 if (session() != nullptr && |
197 session_->error() != QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { | 174 session()->error() != QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { |
198 // We've successfully created a session but we're not connected, and there | 175 // We've successfully created a session but we're not connected, and there |
199 // is no stateless reject to recover from. Give up trying. | 176 // is no stateless reject to recover from. Give up trying. |
200 break; | 177 break; |
201 } | 178 } |
202 } | 179 } |
203 if (!connected() && | 180 if (!connected() && |
204 GetNumSentClientHellos() > QuicCryptoClientStream::kMaxClientHellos && | 181 GetNumSentClientHellos() > QuicCryptoClientStream::kMaxClientHellos && |
205 session_ != nullptr && | 182 session() != nullptr && |
206 session_->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { | 183 session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { |
207 // The overall connection failed due too many stateless rejects. | 184 // The overall connection failed due too many stateless rejects. |
208 connection_error_ = QUIC_CRYPTO_TOO_MANY_REJECTS; | 185 set_connection_error(QUIC_CRYPTO_TOO_MANY_REJECTS); |
209 } | 186 } |
210 return session_->connection()->connected(); | 187 return session()->connection()->connected(); |
211 } | |
212 | |
213 QuicClientSession* QuicSimpleClient::CreateQuicClientSession( | |
214 const QuicConfig& config, | |
215 QuicConnection* connection, | |
216 const QuicServerId& server_id, | |
217 QuicCryptoClientConfig* crypto_config) { | |
218 return new QuicClientSession(config, connection, server_id_, &crypto_config_); | |
219 } | 188 } |
220 | 189 |
221 void QuicSimpleClient::StartConnect() { | 190 void QuicSimpleClient::StartConnect() { |
222 DCHECK(initialized_); | 191 DCHECK(initialized_); |
223 DCHECK(!connected()); | 192 DCHECK(!connected()); |
224 | 193 |
225 writer_.reset(CreateQuicPacketWriter()); | 194 set_writer(CreateQuicPacketWriter()); |
226 | 195 |
227 DummyPacketWriterFactory factory(writer_.get()); | 196 DummyPacketWriterFactory factory(writer()); |
228 | 197 |
229 if (connected_or_attempting_connect_) { | 198 if (connected_or_attempting_connect()) { |
230 // Before we destroy the last session and create a new one, gather its stats | 199 // Before we destroy the last session and create a new one, gather its stats |
231 // and update the stats for the overall connection. | 200 // and update the stats for the overall connection. |
232 num_sent_client_hellos_ += session_->GetNumSentClientHellos(); | 201 UpdateStats(); |
233 if (session_->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { | 202 if (session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { |
234 // If the last error was due to a stateless reject, queue up the data to | 203 // If the last error was due to a stateless reject, queue up the data to |
235 // be resent on the next successful connection. | 204 // be resent on the next successful connection. |
236 // TODO(jokulik): I'm a little bit concerned about ordering here. Maybe | 205 // TODO(jokulik): I'm a little bit concerned about ordering here. Maybe |
237 // we should just maintain one queue? | 206 // we should just maintain one queue? |
238 ++num_stateless_rejects_received_; | |
239 DCHECK(data_to_resend_on_connect_.empty()); | 207 DCHECK(data_to_resend_on_connect_.empty()); |
240 data_to_resend_on_connect_.swap(data_sent_before_handshake_); | 208 data_to_resend_on_connect_.swap(data_sent_before_handshake_); |
241 } | 209 } |
242 } | 210 } |
243 | 211 |
244 session_.reset(CreateQuicClientSession( | 212 CreateQuicClientSession(new QuicConnection( |
245 config_, | 213 GetNextConnectionId(), server_address_, helper_.get(), factory, |
246 new QuicConnection(GetNextConnectionId(), server_address_, helper_.get(), | 214 /* owns_writer= */ false, Perspective::IS_CLIENT, server_id().is_https(), |
247 factory, | 215 supported_versions())); |
248 /* owns_writer= */ false, Perspective::IS_CLIENT, | |
249 server_id_.is_https(), supported_versions_), | |
250 server_id_, &crypto_config_)); | |
251 if (initial_max_packet_length_ != 0) { | |
252 session_->connection()->set_max_packet_length(initial_max_packet_length_); | |
253 } | |
254 session_->Initialize(); | |
255 session_->CryptoConnect(); | |
256 connected_or_attempting_connect_ = true; | |
257 } | |
258 | 216 |
259 bool QuicSimpleClient::EncryptionBeingEstablished() { | 217 session()->Initialize(); |
260 return !session_->IsEncryptionEstablished() && | 218 session()->CryptoConnect(); |
261 session_->connection()->connected(); | 219 set_connected_or_attempting_connect(true); |
262 } | 220 } |
263 | 221 |
264 void QuicSimpleClient::Disconnect() { | 222 void QuicSimpleClient::Disconnect() { |
265 DCHECK(initialized_); | 223 DCHECK(initialized_); |
266 | 224 |
267 if (connected()) { | 225 if (connected()) { |
268 session()->connection()->SendConnectionClose(QUIC_PEER_GOING_AWAY); | 226 session()->connection()->SendConnectionClose(QUIC_PEER_GOING_AWAY); |
269 } | 227 } |
270 STLDeleteElements(&data_to_resend_on_connect_); | 228 STLDeleteElements(&data_to_resend_on_connect_); |
271 STLDeleteElements(&data_sent_before_handshake_); | 229 STLDeleteElements(&data_sent_before_handshake_); |
272 | 230 |
273 writer_.reset(); | 231 reset_writer(); |
274 packet_reader_.reset(); | 232 packet_reader_.reset(); |
275 | 233 |
276 initialized_ = false; | 234 initialized_ = false; |
277 } | 235 } |
278 | 236 |
279 void QuicSimpleClient::SendRequest(const HttpRequestInfo& headers, | 237 void QuicSimpleClient::SendRequest(const HttpRequestInfo& headers, |
280 base::StringPiece body, | 238 StringPiece body, |
281 bool fin) { | 239 bool fin) { |
282 QuicSpdyClientStream* stream = CreateReliableClientStream(); | 240 QuicSpdyClientStream* stream = CreateReliableClientStream(); |
283 if (stream == nullptr) { | 241 if (stream == nullptr) { |
284 LOG(DFATAL) << "stream creation failed!"; | 242 LOG(DFATAL) << "stream creation failed!"; |
285 return; | 243 return; |
286 } | 244 } |
287 SpdyHeaderBlock header_block; | 245 SpdyHeaderBlock header_block; |
288 SpdyMajorVersion spdy_version = | 246 SpdyMajorVersion spdy_version = |
289 SpdyUtils::GetSpdyVersionForQuicVersion(stream->version()); | 247 SpdyUtils::GetSpdyVersionForQuicVersion(stream->version()); |
290 CreateSpdyHeadersFromHttpRequest(headers, headers.extra_headers, spdy_version, | 248 CreateSpdyHeadersFromHttpRequest(headers, headers.extra_headers, spdy_version, |
291 true, &header_block); | 249 true, &header_block); |
292 stream->set_visitor(this); | 250 stream->set_visitor(this); |
293 stream->SendRequest(header_block, body, fin); | 251 stream->SendRequest(header_block, body, fin); |
294 if (FLAGS_enable_quic_stateless_reject_support) { | 252 if (FLAGS_enable_quic_stateless_reject_support) { |
295 // Record this in case we need to resend. | 253 // Record this in case we need to resend. |
296 auto new_headers = new HttpRequestInfo; | 254 auto new_headers = new HttpRequestInfo; |
297 *new_headers = headers; | 255 *new_headers = headers; |
298 auto data_to_resend = | 256 auto data_to_resend = |
299 new ClientQuicDataToResend(new_headers, body, fin, this); | 257 new ClientQuicDataToResend(new_headers, body, fin, this); |
300 MaybeAddQuicDataToResend(data_to_resend); | 258 MaybeAddQuicDataToResend(data_to_resend); |
301 } | 259 } |
302 } | 260 } |
303 | 261 |
304 void QuicSimpleClient::MaybeAddQuicDataToResend( | 262 void QuicSimpleClient::MaybeAddQuicDataToResend( |
305 QuicDataToResend* data_to_resend) { | 263 QuicDataToResend* data_to_resend) { |
306 DCHECK(FLAGS_enable_quic_stateless_reject_support); | 264 DCHECK(FLAGS_enable_quic_stateless_reject_support); |
307 if (session_->IsCryptoHandshakeConfirmed()) { | 265 if (session()->IsCryptoHandshakeConfirmed()) { |
308 // The handshake is confirmed. No need to continue saving requests to | 266 // The handshake is confirmed. No need to continue saving requests to |
309 // resend. | 267 // resend. |
310 STLDeleteElements(&data_sent_before_handshake_); | 268 STLDeleteElements(&data_sent_before_handshake_); |
311 delete data_to_resend; | 269 delete data_to_resend; |
312 return; | 270 return; |
313 } | 271 } |
314 | 272 |
315 // The handshake is not confirmed. Push the data onto the queue of data to | 273 // The handshake is not confirmed. Push the data onto the queue of data to |
316 // resend if statelessly rejected. | 274 // resend if statelessly rejected. |
317 data_sent_before_handshake_.push_back(data_to_resend); | 275 data_sent_before_handshake_.push_back(data_to_resend); |
318 } | 276 } |
319 | 277 |
320 void QuicSimpleClient::SendRequestAndWaitForResponse( | 278 void QuicSimpleClient::SendRequestAndWaitForResponse( |
321 const HttpRequestInfo& request, | 279 const HttpRequestInfo& request, |
322 base::StringPiece body, | 280 StringPiece body, |
323 bool fin) { | 281 bool fin) { |
324 SendRequest(request, body, fin); | 282 SendRequest(request, body, fin); |
325 while (WaitForEvents()) {} | 283 while (WaitForEvents()) {} |
326 } | 284 } |
327 | 285 |
328 void QuicSimpleClient::SendRequestsAndWaitForResponse( | 286 void QuicSimpleClient::SendRequestsAndWaitForResponse( |
329 const base::CommandLine::StringVector& url_list) { | 287 const base::CommandLine::StringVector& url_list) { |
330 for (size_t i = 0; i < url_list.size(); ++i) { | 288 for (size_t i = 0; i < url_list.size(); ++i) { |
331 HttpRequestInfo request; | 289 HttpRequestInfo request; |
332 request.method = "GET"; | 290 request.method = "GET"; |
333 request.url = GURL(url_list[i]); | 291 request.url = GURL(url_list[i]); |
334 SendRequest(request, "", true); | 292 SendRequest(request, "", true); |
335 } | 293 } |
336 | 294 |
337 while (WaitForEvents()) {} | 295 while (WaitForEvents()) {} |
338 } | 296 } |
339 | 297 |
340 QuicSpdyClientStream* QuicSimpleClient::CreateReliableClientStream() { | |
341 if (!connected()) { | |
342 return nullptr; | |
343 } | |
344 | |
345 return session_->CreateOutgoingDynamicStream(); | |
346 } | |
347 | |
348 void QuicSimpleClient::WaitForStreamToClose(QuicStreamId id) { | |
349 DCHECK(connected()); | |
350 | |
351 while (connected() && !session_->IsClosedStream(id)) { | |
352 WaitForEvents(); | |
353 } | |
354 } | |
355 | |
356 void QuicSimpleClient::WaitForCryptoHandshakeConfirmed() { | |
357 DCHECK(connected()); | |
358 | |
359 while (connected() && !session_->IsCryptoHandshakeConfirmed()) { | |
360 WaitForEvents(); | |
361 } | |
362 } | |
363 | |
364 bool QuicSimpleClient::WaitForEvents() { | 298 bool QuicSimpleClient::WaitForEvents() { |
365 DCHECK(connected()); | 299 DCHECK(connected()); |
366 | 300 |
367 base::RunLoop().RunUntilIdle(); | 301 base::RunLoop().RunUntilIdle(); |
368 | 302 |
369 DCHECK(session_ != nullptr); | 303 DCHECK(session() != nullptr); |
370 if (!connected() && | 304 if (!connected() && |
371 session_->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { | 305 session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { |
372 DCHECK(FLAGS_enable_quic_stateless_reject_support); | 306 DCHECK(FLAGS_enable_quic_stateless_reject_support); |
373 DVLOG(1) << "Detected stateless reject while waiting for events. " | 307 DVLOG(1) << "Detected stateless reject while waiting for events. " |
374 << "Attempting to reconnect."; | 308 << "Attempting to reconnect."; |
375 Connect(); | 309 Connect(); |
376 } | 310 } |
377 | 311 |
378 return session_->num_active_requests() != 0; | 312 return session()->num_active_requests() != 0; |
379 } | 313 } |
380 | 314 |
381 bool QuicSimpleClient::MigrateSocket(const IPAddressNumber& new_host) { | 315 bool QuicSimpleClient::MigrateSocket(const IPAddressNumber& new_host) { |
382 if (!connected()) { | 316 if (!connected()) { |
383 return false; | 317 return false; |
384 } | 318 } |
385 | 319 |
386 bind_to_address_ = new_host; | 320 bind_to_address_ = new_host; |
387 if (!CreateUDPSocket()) { | 321 if (!CreateUDPSocket()) { |
388 return false; | 322 return false; |
389 } | 323 } |
390 | 324 |
391 session_->connection()->SetSelfAddress(client_address_); | 325 session()->connection()->SetSelfAddress(client_address_); |
392 | 326 |
393 QuicPacketWriter* writer = CreateQuicPacketWriter(); | 327 QuicPacketWriter* writer = CreateQuicPacketWriter(); |
394 DummyPacketWriterFactory factory(writer); | 328 DummyPacketWriterFactory factory(writer); |
395 if (writer_.get() != writer) { | 329 set_writer(writer); |
396 writer_.reset(writer); | 330 session()->connection()->SetQuicPacketWriter(writer, false); |
397 } | |
398 session_->connection()->SetQuicPacketWriter(writer, false); | |
399 | 331 |
400 return true; | 332 return true; |
401 } | 333 } |
402 | 334 |
403 void QuicSimpleClient::OnClose(QuicDataStream* stream) { | 335 void QuicSimpleClient::OnClose(QuicDataStream* stream) { |
404 DCHECK(stream != nullptr); | 336 DCHECK(stream != nullptr); |
405 QuicSpdyClientStream* client_stream = | 337 QuicSpdyClientStream* client_stream = |
406 static_cast<QuicSpdyClientStream*>(stream); | 338 static_cast<QuicSpdyClientStream*>(stream); |
407 HttpResponseInfo response; | 339 HttpResponseInfo response; |
408 SpdyMajorVersion spdy_version = | 340 SpdyMajorVersion spdy_version = |
409 SpdyUtils::GetSpdyVersionForQuicVersion(client_stream->version()); | 341 SpdyUtils::GetSpdyVersionForQuicVersion(client_stream->version()); |
410 SpdyHeadersToHttpResponse(client_stream->headers(), spdy_version, &response); | 342 SpdyHeadersToHttpResponse(client_stream->headers(), spdy_version, &response); |
411 if (response_listener_.get() != nullptr) { | 343 if (response_listener_.get() != nullptr) { |
412 response_listener_->OnCompleteResponse( | 344 response_listener_->OnCompleteResponse( |
413 stream->id(), *response.headers, client_stream->data()); | 345 stream->id(), *response.headers, client_stream->data()); |
414 } | 346 } |
415 | 347 |
416 // Store response headers and body. | 348 // Store response headers and body. |
417 if (store_response_) { | 349 if (store_response_) { |
418 latest_response_code_ = client_stream->response_code(); | 350 latest_response_code_ = client_stream->response_code(); |
419 response.headers->GetNormalizedHeaders(&latest_response_headers_); | 351 response.headers->GetNormalizedHeaders(&latest_response_headers_); |
420 latest_response_body_ = client_stream->data(); | 352 latest_response_body_ = client_stream->data(); |
421 } | 353 } |
422 } | 354 } |
423 | 355 |
424 bool QuicSimpleClient::connected() const { | |
425 return session_.get() && session_->connection() && | |
426 session_->connection()->connected(); | |
427 } | |
428 | |
429 bool QuicSimpleClient::goaway_received() const { | |
430 return session_ != nullptr && session_->goaway_received(); | |
431 } | |
432 | |
433 size_t QuicSimpleClient::latest_response_code() const { | 356 size_t QuicSimpleClient::latest_response_code() const { |
434 LOG_IF(DFATAL, !store_response_) << "Response not stored!"; | 357 LOG_IF(DFATAL, !store_response_) << "Response not stored!"; |
435 return latest_response_code_; | 358 return latest_response_code_; |
436 } | 359 } |
437 | 360 |
438 const string& QuicSimpleClient::latest_response_headers() const { | 361 const string& QuicSimpleClient::latest_response_headers() const { |
439 LOG_IF(DFATAL, !store_response_) << "Response not stored!"; | 362 LOG_IF(DFATAL, !store_response_) << "Response not stored!"; |
440 return latest_response_headers_; | 363 return latest_response_headers_; |
441 } | 364 } |
442 | 365 |
443 const string& QuicSimpleClient::latest_response_body() const { | 366 const string& QuicSimpleClient::latest_response_body() const { |
444 LOG_IF(DFATAL, !store_response_) << "Response not stored!"; | 367 LOG_IF(DFATAL, !store_response_) << "Response not stored!"; |
445 return latest_response_body_; | 368 return latest_response_body_; |
446 } | 369 } |
447 | 370 |
448 int QuicSimpleClient::GetNumSentClientHellos() { | |
449 // If we are not actively attempting to connect, the session object | |
450 // corresponds to the previous connection and should not be used. | |
451 const int current_session_hellos = !connected_or_attempting_connect_ | |
452 ? 0 | |
453 : session_->GetNumSentClientHellos(); | |
454 return num_sent_client_hellos_ + current_session_hellos; | |
455 } | |
456 | |
457 QuicErrorCode QuicSimpleClient::connection_error() const { | |
458 // Return the high-level error if there was one. Otherwise, return the | |
459 // connection error from the last session. | |
460 if (connection_error_ != QUIC_NO_ERROR) { | |
461 return connection_error_; | |
462 } | |
463 if (session_.get() == nullptr) { | |
464 return QUIC_NO_ERROR; | |
465 } | |
466 return session_->error(); | |
467 } | |
468 | |
469 QuicConnectionId QuicSimpleClient::GetNextConnectionId() { | |
470 QuicConnectionId server_designated_id = GetNextServerDesignatedConnectionId(); | |
471 return server_designated_id ? server_designated_id | |
472 : GenerateNewConnectionId(); | |
473 } | |
474 | |
475 QuicConnectionId QuicSimpleClient::GetNextServerDesignatedConnectionId() { | |
476 QuicCryptoClientConfig::CachedState* cached = | |
477 crypto_config_.LookupOrCreate(server_id_); | |
478 // If the cached state indicates that we should use a server-designated | |
479 // connection ID, then return that connection ID. | |
480 CHECK(cached != nullptr) << "QuicClientCryptoConfig::LookupOrCreate returned " | |
481 << "unexpected nullptr."; | |
482 return cached->has_server_designated_connection_id() | |
483 ? cached->GetNextServerDesignatedConnectionId() | |
484 : 0; | |
485 } | |
486 | |
487 QuicConnectionId QuicSimpleClient::GenerateNewConnectionId() { | 371 QuicConnectionId QuicSimpleClient::GenerateNewConnectionId() { |
488 return helper_->GetRandomGenerator()->RandUint64(); | 372 return helper_->GetRandomGenerator()->RandUint64(); |
489 } | 373 } |
490 | 374 |
491 QuicConnectionHelper* QuicSimpleClient::CreateQuicConnectionHelper() { | 375 QuicConnectionHelper* QuicSimpleClient::CreateQuicConnectionHelper() { |
492 return new QuicConnectionHelper(base::ThreadTaskRunnerHandle::Get().get(), | 376 return new QuicConnectionHelper(base::ThreadTaskRunnerHandle::Get().get(), |
493 &clock_, QuicRandom::GetInstance()); | 377 &clock_, QuicRandom::GetInstance()); |
494 } | 378 } |
495 | 379 |
496 QuicPacketWriter* QuicSimpleClient::CreateQuicPacketWriter() { | 380 QuicPacketWriter* QuicSimpleClient::CreateQuicPacketWriter() { |
497 return new QuicDefaultPacketWriter(socket_.get()); | 381 return new QuicDefaultPacketWriter(socket_.get()); |
498 } | 382 } |
499 | 383 |
500 void QuicSimpleClient::OnReadError(int result) { | 384 void QuicSimpleClient::OnReadError(int result) { |
501 LOG(ERROR) << "QuicSimpleClient read failed: " << ErrorToShortString(result); | 385 LOG(ERROR) << "QuicSimpleClient read failed: " << ErrorToShortString(result); |
502 Disconnect(); | 386 Disconnect(); |
503 } | 387 } |
504 | 388 |
505 bool QuicSimpleClient::OnPacket(const QuicEncryptedPacket& packet, | 389 bool QuicSimpleClient::OnPacket(const QuicEncryptedPacket& packet, |
506 IPEndPoint local_address, | 390 IPEndPoint local_address, |
507 IPEndPoint peer_address) { | 391 IPEndPoint peer_address) { |
508 session_->connection()->ProcessUdpPacket(local_address, peer_address, packet); | 392 session()->connection()->ProcessUdpPacket(local_address, peer_address, |
509 if (!session_->connection()->connected()) { | 393 packet); |
| 394 if (!session()->connection()->connected()) { |
510 return false; | 395 return false; |
511 } | 396 } |
512 | 397 |
513 return true; | 398 return true; |
514 } | 399 } |
515 | 400 |
516 } // namespace tools | 401 } // namespace tools |
517 } // namespace net | 402 } // namespace net |
OLD | NEW |