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_client.h" | 5 #include "net/tools/quic/quic_client.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <netinet/in.h> | 8 #include <netinet/in.h> |
9 #include <string.h> | 9 #include <string.h> |
10 #include <sys/epoll.h> | 10 #include <sys/epoll.h> |
11 #include <sys/socket.h> | 11 #include <sys/socket.h> |
12 #include <unistd.h> | 12 #include <unistd.h> |
13 | 13 |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "net/base/net_util.h" | 15 #include "net/base/net_util.h" |
16 #include "net/quic/crypto/quic_random.h" | 16 #include "net/quic/crypto/quic_random.h" |
17 #include "net/quic/quic_connection.h" | 17 #include "net/quic/quic_connection.h" |
18 #include "net/quic/quic_crypto_client_stream.h" | |
19 #include "net/quic/quic_data_reader.h" | 18 #include "net/quic/quic_data_reader.h" |
20 #include "net/quic/quic_flags.h" | 19 #include "net/quic/quic_flags.h" |
21 #include "net/quic/quic_protocol.h" | 20 #include "net/quic/quic_protocol.h" |
22 #include "net/quic/quic_server_id.h" | 21 #include "net/quic/quic_server_id.h" |
23 #include "net/tools/balsa/balsa_headers.h" | |
24 #include "net/tools/epoll_server/epoll_server.h" | |
25 #include "net/tools/quic/quic_epoll_connection_helper.h" | 22 #include "net/tools/quic/quic_epoll_connection_helper.h" |
26 #include "net/tools/quic/quic_socket_utils.h" | 23 #include "net/tools/quic/quic_socket_utils.h" |
27 #include "net/tools/quic/quic_spdy_client_stream.h" | |
28 #include "net/tools/quic/spdy_balsa_utils.h" | 24 #include "net/tools/quic/spdy_balsa_utils.h" |
29 | 25 |
30 #ifndef SO_RXQ_OVFL | 26 #ifndef SO_RXQ_OVFL |
31 #define SO_RXQ_OVFL 40 | 27 #define SO_RXQ_OVFL 40 |
32 #endif | 28 #endif |
33 | 29 |
34 using std::string; | 30 using std::string; |
35 using std::vector; | 31 using std::vector; |
36 | 32 |
37 namespace net { | 33 namespace net { |
(...skipping 15 matching lines...) Expand all Loading... |
53 server_id, | 49 server_id, |
54 supported_versions, | 50 supported_versions, |
55 QuicConfig(), | 51 QuicConfig(), |
56 epoll_server) {} | 52 epoll_server) {} |
57 | 53 |
58 QuicClient::QuicClient(IPEndPoint server_address, | 54 QuicClient::QuicClient(IPEndPoint server_address, |
59 const QuicServerId& server_id, | 55 const QuicServerId& server_id, |
60 const QuicVersionVector& supported_versions, | 56 const QuicVersionVector& supported_versions, |
61 const QuicConfig& config, | 57 const QuicConfig& config, |
62 EpollServer* epoll_server) | 58 EpollServer* epoll_server) |
63 : server_address_(server_address), | 59 : QuicClientBase(server_id, supported_versions, config), |
64 server_id_(server_id), | 60 server_address_(server_address), |
65 config_(config), | |
66 local_port_(0), | 61 local_port_(0), |
67 epoll_server_(epoll_server), | 62 epoll_server_(epoll_server), |
68 fd_(-1), | 63 fd_(-1), |
69 helper_(CreateQuicConnectionHelper()), | 64 helper_(CreateQuicConnectionHelper()), |
70 initialized_(false), | 65 initialized_(false), |
71 packets_dropped_(0), | 66 packets_dropped_(0), |
72 overflow_supported_(false), | 67 overflow_supported_(false), |
73 supported_versions_(supported_versions), | |
74 store_response_(false), | 68 store_response_(false), |
75 latest_response_code_(-1), | 69 latest_response_code_(-1) {} |
76 initial_max_packet_length_(0), | |
77 num_stateless_rejects_received_(0), | |
78 num_sent_client_hellos_(0), | |
79 connection_error_(QUIC_NO_ERROR), | |
80 connected_or_attempting_connect_(false) {} | |
81 | 70 |
82 QuicClient::~QuicClient() { | 71 QuicClient::~QuicClient() { |
83 if (connected()) { | 72 if (connected()) { |
84 session()->connection()->SendConnectionClose(QUIC_PEER_GOING_AWAY); | 73 session()->connection()->SendConnectionClose(QUIC_PEER_GOING_AWAY); |
85 } | 74 } |
| 75 |
86 STLDeleteElements(&data_to_resend_on_connect_); | 76 STLDeleteElements(&data_to_resend_on_connect_); |
87 STLDeleteElements(&data_sent_before_handshake_); | 77 STLDeleteElements(&data_sent_before_handshake_); |
88 | 78 |
89 CleanUpUDPSocketImpl(); | 79 CleanUpUDPSocketImpl(); |
90 } | 80 } |
91 | 81 |
92 bool QuicClient::Initialize() { | 82 bool QuicClient::Initialize() { |
93 DCHECK(!initialized_); | 83 QuicClientBase::Initialize(); |
94 | |
95 num_sent_client_hellos_ = 0; | |
96 num_stateless_rejects_received_ = 0; | |
97 connection_error_ = QUIC_NO_ERROR; | |
98 connected_or_attempting_connect_ = false; | |
99 | 84 |
100 // If an initial flow control window has not explicitly been set, then use the | 85 // If an initial flow control window has not explicitly been set, then use the |
101 // same values that Chrome uses. | 86 // same values that Chrome uses. |
102 const uint32 kSessionMaxRecvWindowSize = 15 * 1024 * 1024; // 15 MB | 87 const uint32 kSessionMaxRecvWindowSize = 15 * 1024 * 1024; // 15 MB |
103 const uint32 kStreamMaxRecvWindowSize = 6 * 1024 * 1024; // 6 MB | 88 const uint32 kStreamMaxRecvWindowSize = 6 * 1024 * 1024; // 6 MB |
104 if (config_.GetInitialStreamFlowControlWindowToSend() == | 89 if (config()->GetInitialStreamFlowControlWindowToSend() == |
105 kMinimumFlowControlSendWindow) { | 90 kMinimumFlowControlSendWindow) { |
106 config_.SetInitialStreamFlowControlWindowToSend(kStreamMaxRecvWindowSize); | 91 config()->SetInitialStreamFlowControlWindowToSend(kStreamMaxRecvWindowSize); |
107 } | 92 } |
108 if (config_.GetInitialSessionFlowControlWindowToSend() == | 93 if (config()->GetInitialSessionFlowControlWindowToSend() == |
109 kMinimumFlowControlSendWindow) { | 94 kMinimumFlowControlSendWindow) { |
110 config_.SetInitialSessionFlowControlWindowToSend(kSessionMaxRecvWindowSize); | 95 config()->SetInitialSessionFlowControlWindowToSend( |
| 96 kSessionMaxRecvWindowSize); |
111 } | 97 } |
112 | 98 |
113 epoll_server_->set_timeout_in_us(50 * 1000); | 99 epoll_server_->set_timeout_in_us(50 * 1000); |
114 | 100 |
115 if (!CreateUDPSocket()) { | 101 if (!CreateUDPSocket()) { |
116 return false; | 102 return false; |
117 } | 103 } |
118 | 104 |
119 epoll_server_->RegisterFD(fd_, this, kEpollFlags); | 105 epoll_server_->RegisterFD(fd_, this, kEpollFlags); |
120 initialized_ = true; | 106 initialized_ = true; |
121 return true; | 107 return true; |
122 } | 108 } |
123 | 109 |
124 QuicClient::DummyPacketWriterFactory::DummyPacketWriterFactory( | |
125 QuicPacketWriter* writer) | |
126 : writer_(writer) {} | |
127 | |
128 QuicClient::DummyPacketWriterFactory::~DummyPacketWriterFactory() {} | |
129 | |
130 QuicPacketWriter* QuicClient::DummyPacketWriterFactory::Create( | |
131 QuicConnection* /*connection*/) const { | |
132 return writer_; | |
133 } | |
134 | |
135 QuicClient::QuicDataToResend::QuicDataToResend(BalsaHeaders* headers, | 110 QuicClient::QuicDataToResend::QuicDataToResend(BalsaHeaders* headers, |
136 StringPiece body, | 111 StringPiece body, |
137 bool fin) | 112 bool fin) |
138 : headers_(headers), body_(body), fin_(fin) {} | 113 : headers_(headers), body_(body), fin_(fin) {} |
139 | 114 |
140 QuicClient::QuicDataToResend::~QuicDataToResend() { | 115 QuicClient::QuicDataToResend::~QuicDataToResend() { |
141 if (headers_) { | 116 if (headers_) { |
142 delete headers_; | 117 delete headers_; |
143 } | 118 } |
144 } | 119 } |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 } | 194 } |
220 if (FLAGS_enable_quic_stateless_reject_support && connected() && | 195 if (FLAGS_enable_quic_stateless_reject_support && connected() && |
221 !data_to_resend_on_connect_.empty()) { | 196 !data_to_resend_on_connect_.empty()) { |
222 // A connection has been established and there was previously queued data | 197 // A connection has been established and there was previously queued data |
223 // to resend. Resend it and empty the queue. | 198 // to resend. Resend it and empty the queue. |
224 for (QuicDataToResend* data : data_to_resend_on_connect_) { | 199 for (QuicDataToResend* data : data_to_resend_on_connect_) { |
225 data->Resend(); | 200 data->Resend(); |
226 } | 201 } |
227 STLDeleteElements(&data_to_resend_on_connect_); | 202 STLDeleteElements(&data_to_resend_on_connect_); |
228 } | 203 } |
229 if (session_.get() != nullptr && | 204 if (session() != nullptr && |
230 session_->error() != QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { | 205 session()->error() != QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { |
231 // We've successfully created a session but we're not connected, and there | 206 // We've successfully created a session but we're not connected, and there |
232 // is no stateless reject to recover from. Give up trying. | 207 // is no stateless reject to recover from. Give up trying. |
233 break; | 208 break; |
234 } | 209 } |
235 } | 210 } |
236 if (!connected() && | 211 if (!connected() && |
237 GetNumSentClientHellos() > QuicCryptoClientStream::kMaxClientHellos && | 212 GetNumSentClientHellos() > QuicCryptoClientStream::kMaxClientHellos && |
238 session_ != nullptr && | 213 session() != nullptr && |
239 session_->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { | 214 session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { |
240 // The overall connection failed due too many stateless rejects. | 215 // The overall connection failed due too many stateless rejects. |
241 connection_error_ = QUIC_CRYPTO_TOO_MANY_REJECTS; | 216 set_connection_error(QUIC_CRYPTO_TOO_MANY_REJECTS); |
242 } | 217 } |
243 return session_->connection()->connected(); | 218 return session()->connection()->connected(); |
244 } | |
245 | |
246 QuicClientSession* QuicClient::CreateQuicClientSession( | |
247 const QuicConfig& config, | |
248 QuicConnection* connection, | |
249 const QuicServerId& server_id, | |
250 QuicCryptoClientConfig* crypto_config) { | |
251 return new QuicClientSession(config, connection, server_id_, &crypto_config_); | |
252 } | 219 } |
253 | 220 |
254 void QuicClient::StartConnect() { | 221 void QuicClient::StartConnect() { |
255 DCHECK(initialized_); | 222 DCHECK(initialized_); |
256 DCHECK(!connected()); | 223 DCHECK(!connected()); |
257 | 224 |
258 QuicPacketWriter* writer = CreateQuicPacketWriter(); | 225 QuicPacketWriter* writer = CreateQuicPacketWriter(); |
259 | 226 |
260 DummyPacketWriterFactory factory(writer); | 227 DummyPacketWriterFactory factory(writer); |
261 | 228 |
262 if (connected_or_attempting_connect_) { | 229 if (connected_or_attempting_connect()) { |
263 // Before we destroy the last session and create a new one, gather its stats | 230 // Before we destroy the last session and create a new one, gather its stats |
264 // and update the stats for the overall connection. | 231 // and update the stats for the overall connection. |
265 num_sent_client_hellos_ += session_->GetNumSentClientHellos(); | 232 UpdateStats(); |
266 if (session_->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { | 233 if (session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { |
267 // If the last error was due to a stateless reject, queue up the data to | 234 // If the last error was due to a stateless reject, queue up the data to |
268 // be resent on the next successful connection. | 235 // be resent on the next successful connection. |
269 // TODO(jokulik): I'm a little bit concerned about ordering here. Maybe | 236 // TODO(jokulik): I'm a little bit concerned about ordering here. Maybe |
270 // we should just maintain one queue? | 237 // we should just maintain one queue? |
271 ++num_stateless_rejects_received_; | |
272 DCHECK(data_to_resend_on_connect_.empty()); | 238 DCHECK(data_to_resend_on_connect_.empty()); |
273 data_to_resend_on_connect_.swap(data_sent_before_handshake_); | 239 data_to_resend_on_connect_.swap(data_sent_before_handshake_); |
274 } | 240 } |
275 } | 241 } |
276 | 242 |
277 session_.reset(CreateQuicClientSession( | 243 CreateQuicClientSession(new QuicConnection( |
278 config_, | 244 GetNextConnectionId(), server_address_, helper_.get(), factory, |
279 new QuicConnection(GetNextConnectionId(), server_address_, helper_.get(), | 245 /* owns_writer= */ false, Perspective::IS_CLIENT, server_id().is_https(), |
280 factory, | 246 supported_versions())); |
281 /* owns_writer= */ false, Perspective::IS_CLIENT, | |
282 server_id_.is_https(), supported_versions_), | |
283 server_id_, &crypto_config_)); | |
284 if (initial_max_packet_length_ != 0) { | |
285 session_->connection()->set_max_packet_length(initial_max_packet_length_); | |
286 } | |
287 | 247 |
288 // Reset |writer_| after |session_| so that the old writer outlives the old | 248 // Reset |writer_| after |session()| so that the old writer outlives the old |
289 // session. | 249 // session. |
290 if (writer_.get() != writer) { | 250 set_writer(writer); |
291 writer_.reset(writer); | 251 session()->Initialize(); |
292 } | 252 session()->CryptoConnect(); |
293 session_->Initialize(); | 253 set_connected_or_attempting_connect(true); |
294 session_->CryptoConnect(); | |
295 connected_or_attempting_connect_ = true; | |
296 } | |
297 | |
298 bool QuicClient::EncryptionBeingEstablished() { | |
299 return !session_->IsEncryptionEstablished() && | |
300 session_->connection()->connected(); | |
301 } | 254 } |
302 | 255 |
303 void QuicClient::Disconnect() { | 256 void QuicClient::Disconnect() { |
304 DCHECK(initialized_); | 257 DCHECK(initialized_); |
305 | 258 |
306 if (connected()) { | 259 if (connected()) { |
307 session()->connection()->SendConnectionClose(QUIC_PEER_GOING_AWAY); | 260 session()->connection()->SendConnectionClose(QUIC_PEER_GOING_AWAY); |
308 } | 261 } |
309 STLDeleteElements(&data_to_resend_on_connect_); | 262 STLDeleteElements(&data_to_resend_on_connect_); |
310 STLDeleteElements(&data_sent_before_handshake_); | 263 STLDeleteElements(&data_sent_before_handshake_); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 auto new_headers = new BalsaHeaders; | 297 auto new_headers = new BalsaHeaders; |
345 new_headers->CopyFrom(headers); | 298 new_headers->CopyFrom(headers); |
346 auto data_to_resend = | 299 auto data_to_resend = |
347 new ClientQuicDataToResend(new_headers, body, fin, this); | 300 new ClientQuicDataToResend(new_headers, body, fin, this); |
348 MaybeAddQuicDataToResend(data_to_resend); | 301 MaybeAddQuicDataToResend(data_to_resend); |
349 } | 302 } |
350 } | 303 } |
351 | 304 |
352 void QuicClient::MaybeAddQuicDataToResend(QuicDataToResend* data_to_resend) { | 305 void QuicClient::MaybeAddQuicDataToResend(QuicDataToResend* data_to_resend) { |
353 DCHECK(FLAGS_enable_quic_stateless_reject_support); | 306 DCHECK(FLAGS_enable_quic_stateless_reject_support); |
354 if (session_->IsCryptoHandshakeConfirmed()) { | 307 if (session()->IsCryptoHandshakeConfirmed()) { |
355 // The handshake is confirmed. No need to continue saving requests to | 308 // The handshake is confirmed. No need to continue saving requests to |
356 // resend. | 309 // resend. |
357 STLDeleteElements(&data_sent_before_handshake_); | 310 STLDeleteElements(&data_sent_before_handshake_); |
358 delete data_to_resend; | 311 delete data_to_resend; |
359 return; | 312 return; |
360 } | 313 } |
361 | 314 |
362 // The handshake is not confirmed. Push the data onto the queue of data to | 315 // The handshake is not confirmed. Push the data onto the queue of data to |
363 // resend if statelessly rejected. | 316 // resend if statelessly rejected. |
364 data_sent_before_handshake_.push_back(data_to_resend); | 317 data_sent_before_handshake_.push_back(data_to_resend); |
(...skipping 10 matching lines...) Expand all Loading... |
375 void QuicClient::SendRequestsAndWaitForResponse( | 328 void QuicClient::SendRequestsAndWaitForResponse( |
376 const vector<string>& url_list) { | 329 const vector<string>& url_list) { |
377 for (size_t i = 0; i < url_list.size(); ++i) { | 330 for (size_t i = 0; i < url_list.size(); ++i) { |
378 BalsaHeaders headers; | 331 BalsaHeaders headers; |
379 headers.SetRequestFirstlineFromStringPieces("GET", url_list[i], "HTTP/1.1"); | 332 headers.SetRequestFirstlineFromStringPieces("GET", url_list[i], "HTTP/1.1"); |
380 SendRequest(headers, "", true); | 333 SendRequest(headers, "", true); |
381 } | 334 } |
382 while (WaitForEvents()) {} | 335 while (WaitForEvents()) {} |
383 } | 336 } |
384 | 337 |
385 QuicSpdyClientStream* QuicClient::CreateReliableClientStream() { | |
386 if (!connected()) { | |
387 return nullptr; | |
388 } | |
389 | |
390 return session_->CreateOutgoingDynamicStream(); | |
391 } | |
392 | |
393 void QuicClient::WaitForStreamToClose(QuicStreamId id) { | |
394 DCHECK(connected()); | |
395 | |
396 while (connected() && !session_->IsClosedStream(id)) { | |
397 WaitForEvents(); | |
398 } | |
399 } | |
400 | |
401 void QuicClient::WaitForCryptoHandshakeConfirmed() { | |
402 DCHECK(connected()); | |
403 | |
404 while (connected() && !session_->IsCryptoHandshakeConfirmed()) { | |
405 WaitForEvents(); | |
406 } | |
407 } | |
408 | |
409 bool QuicClient::WaitForEvents() { | 338 bool QuicClient::WaitForEvents() { |
410 DCHECK(connected()); | 339 DCHECK(connected()); |
411 | 340 |
412 epoll_server_->WaitForEventsAndExecuteCallbacks(); | 341 epoll_server_->WaitForEventsAndExecuteCallbacks(); |
413 | 342 |
414 DCHECK(session_ != nullptr); | 343 DCHECK(session() != nullptr); |
415 if (!connected() && | 344 if (!connected() && |
416 session_->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { | 345 session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { |
417 DCHECK(FLAGS_enable_quic_stateless_reject_support); | 346 DCHECK(FLAGS_enable_quic_stateless_reject_support); |
418 DVLOG(1) << "Detected stateless reject while waiting for events. " | 347 DVLOG(1) << "Detected stateless reject while waiting for events. " |
419 << "Attempting to reconnect."; | 348 << "Attempting to reconnect."; |
420 Connect(); | 349 Connect(); |
421 } | 350 } |
422 | 351 |
423 return session_->num_active_requests() != 0; | 352 return session()->num_active_requests() != 0; |
424 } | 353 } |
425 | 354 |
426 bool QuicClient::MigrateSocket(const IPAddressNumber& new_host) { | 355 bool QuicClient::MigrateSocket(const IPAddressNumber& new_host) { |
427 if (!connected()) { | 356 if (!connected()) { |
428 return false; | 357 return false; |
429 } | 358 } |
430 | 359 |
431 CleanUpUDPSocket(); | 360 CleanUpUDPSocket(); |
432 | 361 |
433 bind_to_address_ = new_host; | 362 bind_to_address_ = new_host; |
434 if (!CreateUDPSocket()) { | 363 if (!CreateUDPSocket()) { |
435 return false; | 364 return false; |
436 } | 365 } |
437 | 366 |
438 epoll_server_->RegisterFD(fd_, this, kEpollFlags); | 367 epoll_server_->RegisterFD(fd_, this, kEpollFlags); |
439 session_->connection()->SetSelfAddress(client_address_); | 368 session()->connection()->SetSelfAddress(client_address_); |
440 | 369 |
441 QuicPacketWriter* writer = CreateQuicPacketWriter(); | 370 QuicPacketWriter* writer = CreateQuicPacketWriter(); |
442 DummyPacketWriterFactory factory(writer); | 371 DummyPacketWriterFactory factory(writer); |
443 if (writer_.get() != writer) { | 372 set_writer(writer); |
444 writer_.reset(writer); | 373 session()->connection()->SetQuicPacketWriter(writer, false); |
445 } | |
446 session_->connection()->SetQuicPacketWriter(writer, false); | |
447 | 374 |
448 return true; | 375 return true; |
449 } | 376 } |
450 | 377 |
451 void QuicClient::OnEvent(int fd, EpollEvent* event) { | 378 void QuicClient::OnEvent(int fd, EpollEvent* event) { |
452 DCHECK_EQ(fd, fd_); | 379 DCHECK_EQ(fd, fd_); |
453 | 380 |
454 if (event->in_events & EPOLLIN) { | 381 if (event->in_events & EPOLLIN) { |
455 while (connected() && ReadAndProcessPacket()) { | 382 while (connected() && ReadAndProcessPacket()) { |
456 } | 383 } |
457 } | 384 } |
458 if (connected() && (event->in_events & EPOLLOUT)) { | 385 if (connected() && (event->in_events & EPOLLOUT)) { |
459 writer_->SetWritable(); | 386 writer()->SetWritable(); |
460 session_->connection()->OnCanWrite(); | 387 session()->connection()->OnCanWrite(); |
461 } | 388 } |
462 if (event->in_events & EPOLLERR) { | 389 if (event->in_events & EPOLLERR) { |
463 DVLOG(1) << "Epollerr"; | 390 DVLOG(1) << "Epollerr"; |
464 } | 391 } |
465 } | 392 } |
466 | 393 |
467 void QuicClient::OnClose(QuicDataStream* stream) { | 394 void QuicClient::OnClose(QuicDataStream* stream) { |
468 DCHECK(stream != nullptr); | 395 DCHECK(stream != nullptr); |
469 QuicSpdyClientStream* client_stream = | 396 QuicSpdyClientStream* client_stream = |
470 static_cast<QuicSpdyClientStream*>(stream); | 397 static_cast<QuicSpdyClientStream*>(stream); |
471 BalsaHeaders headers; | 398 BalsaHeaders headers; |
472 SpdyBalsaUtils::SpdyHeadersToResponseHeaders(client_stream->headers(), | 399 SpdyBalsaUtils::SpdyHeadersToResponseHeaders(client_stream->headers(), |
473 &headers, stream->version()); | 400 &headers, stream->version()); |
474 | 401 |
475 if (response_listener_.get() != nullptr) { | 402 if (response_listener_.get() != nullptr) { |
476 response_listener_->OnCompleteResponse( | 403 response_listener_->OnCompleteResponse( |
477 stream->id(), headers, client_stream->data()); | 404 stream->id(), headers, client_stream->data()); |
478 } | 405 } |
479 | 406 |
480 // Store response headers and body. | 407 // Store response headers and body. |
481 if (store_response_) { | 408 if (store_response_) { |
482 latest_response_code_ = headers.parsed_response_code(); | 409 latest_response_code_ = headers.parsed_response_code(); |
483 headers.DumpHeadersToString(&latest_response_headers_); | 410 headers.DumpHeadersToString(&latest_response_headers_); |
484 latest_response_body_ = client_stream->data(); | 411 latest_response_body_ = client_stream->data(); |
485 } | 412 } |
486 } | 413 } |
487 | 414 |
488 bool QuicClient::connected() const { | |
489 return session_.get() && session_->connection() && | |
490 session_->connection()->connected(); | |
491 } | |
492 | |
493 bool QuicClient::goaway_received() const { | |
494 return session_ != nullptr && session_->goaway_received(); | |
495 } | |
496 | |
497 size_t QuicClient::latest_response_code() const { | 415 size_t QuicClient::latest_response_code() const { |
498 LOG_IF(DFATAL, !store_response_) << "Response not stored!"; | 416 LOG_IF(DFATAL, !store_response_) << "Response not stored!"; |
499 return latest_response_code_; | 417 return latest_response_code_; |
500 } | 418 } |
501 | 419 |
502 const string& QuicClient::latest_response_headers() const { | 420 const string& QuicClient::latest_response_headers() const { |
503 LOG_IF(DFATAL, !store_response_) << "Response not stored!"; | 421 LOG_IF(DFATAL, !store_response_) << "Response not stored!"; |
504 return latest_response_headers_; | 422 return latest_response_headers_; |
505 } | 423 } |
506 | 424 |
507 const string& QuicClient::latest_response_body() const { | 425 const string& QuicClient::latest_response_body() const { |
508 LOG_IF(DFATAL, !store_response_) << "Response not stored!"; | 426 LOG_IF(DFATAL, !store_response_) << "Response not stored!"; |
509 return latest_response_body_; | 427 return latest_response_body_; |
510 } | 428 } |
511 | 429 |
512 int QuicClient::GetNumSentClientHellos() { | |
513 // If we are not actively attempting to connect, the session object | |
514 // corresponds to the previous connection and should not be used. | |
515 const int current_session_hellos = !connected_or_attempting_connect_ | |
516 ? 0 | |
517 : session_->GetNumSentClientHellos(); | |
518 return num_sent_client_hellos_ + current_session_hellos; | |
519 } | |
520 | |
521 QuicErrorCode QuicClient::connection_error() const { | |
522 // Return the high-level error if there was one. Otherwise, return the | |
523 // connection error from the last session. | |
524 if (connection_error_ != QUIC_NO_ERROR) { | |
525 return connection_error_; | |
526 } | |
527 if (session_.get() == nullptr) { | |
528 return QUIC_NO_ERROR; | |
529 } | |
530 return session_->error(); | |
531 } | |
532 | |
533 QuicConnectionId QuicClient::GetNextConnectionId() { | |
534 QuicConnectionId server_designated_id = GetNextServerDesignatedConnectionId(); | |
535 return server_designated_id ? server_designated_id | |
536 : GenerateNewConnectionId(); | |
537 } | |
538 | |
539 QuicConnectionId QuicClient::GetNextServerDesignatedConnectionId() { | |
540 QuicCryptoClientConfig::CachedState* cached = | |
541 crypto_config_.LookupOrCreate(server_id_); | |
542 // If the cached state indicates that we should use a server-designated | |
543 // connection ID, then return that connection ID. | |
544 CHECK(cached != nullptr) << "QuicClientCryptoConfig::LookupOrCreate returned " | |
545 << "unexpected nullptr."; | |
546 return cached->has_server_designated_connection_id() | |
547 ? cached->GetNextServerDesignatedConnectionId() | |
548 : 0; | |
549 } | |
550 | |
551 QuicConnectionId QuicClient::GenerateNewConnectionId() { | |
552 return QuicRandom::GetInstance()->RandUint64(); | |
553 } | |
554 | |
555 QuicEpollConnectionHelper* QuicClient::CreateQuicConnectionHelper() { | 430 QuicEpollConnectionHelper* QuicClient::CreateQuicConnectionHelper() { |
556 return new QuicEpollConnectionHelper(epoll_server_); | 431 return new QuicEpollConnectionHelper(epoll_server_); |
557 } | 432 } |
558 | 433 |
559 QuicPacketWriter* QuicClient::CreateQuicPacketWriter() { | 434 QuicPacketWriter* QuicClient::CreateQuicPacketWriter() { |
560 return new QuicDefaultPacketWriter(fd_); | 435 return new QuicDefaultPacketWriter(fd_); |
561 } | 436 } |
562 | 437 |
563 int QuicClient::ReadPacket(char* buffer, | 438 int QuicClient::ReadPacket(char* buffer, |
564 int buffer_len, | 439 int buffer_len, |
(...skipping 15 matching lines...) Expand all Loading... |
580 | 455 |
581 int bytes_read = ReadPacket(buf, arraysize(buf), &server_address, &client_ip); | 456 int bytes_read = ReadPacket(buf, arraysize(buf), &server_address, &client_ip); |
582 | 457 |
583 if (bytes_read < 0) { | 458 if (bytes_read < 0) { |
584 return false; | 459 return false; |
585 } | 460 } |
586 | 461 |
587 QuicEncryptedPacket packet(buf, bytes_read, false); | 462 QuicEncryptedPacket packet(buf, bytes_read, false); |
588 | 463 |
589 IPEndPoint client_address(client_ip, client_address_.port()); | 464 IPEndPoint client_address(client_ip, client_address_.port()); |
590 session_->connection()->ProcessUdpPacket( | 465 session()->connection()->ProcessUdpPacket(client_address, server_address, |
591 client_address, server_address, packet); | 466 packet); |
592 return true; | 467 return true; |
593 } | 468 } |
594 | 469 |
595 } // namespace tools | 470 } // namespace tools |
596 } // namespace net | 471 } // namespace net |
OLD | NEW |