| 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 "base/run_loop.h" | 15 #include "base/run_loop.h" |
| 16 #include "base/strings/string_number_conversions.h" |
| 16 #include "net/base/sockaddr_storage.h" | 17 #include "net/base/sockaddr_storage.h" |
| 17 #include "net/quic/core/crypto/quic_random.h" | 18 #include "net/quic/core/crypto/quic_random.h" |
| 18 #include "net/quic/core/quic_bug_tracker.h" | 19 #include "net/quic/core/quic_bug_tracker.h" |
| 19 #include "net/quic/core/quic_connection.h" | 20 #include "net/quic/core/quic_connection.h" |
| 20 #include "net/quic/core/quic_data_reader.h" | 21 #include "net/quic/core/quic_data_reader.h" |
| 21 #include "net/quic/core/quic_flags.h" | 22 #include "net/quic/core/quic_flags.h" |
| 22 #include "net/quic/core/quic_protocol.h" | 23 #include "net/quic/core/quic_protocol.h" |
| 23 #include "net/quic/core/quic_server_id.h" | 24 #include "net/quic/core/quic_server_id.h" |
| 25 #include "net/quic/core/spdy_utils.h" |
| 24 #include "net/tools/quic/quic_epoll_alarm_factory.h" | 26 #include "net/tools/quic/quic_epoll_alarm_factory.h" |
| 25 #include "net/tools/quic/quic_epoll_connection_helper.h" | 27 #include "net/tools/quic/quic_epoll_connection_helper.h" |
| 26 #include "net/tools/quic/quic_socket_utils.h" | 28 #include "net/tools/quic/quic_socket_utils.h" |
| 27 #include "net/tools/quic/spdy_balsa_utils.h" | 29 #include "net/tools/quic/spdy_balsa_utils.h" |
| 28 | 30 |
| 29 #ifndef SO_RXQ_OVFL | 31 #ifndef SO_RXQ_OVFL |
| 30 #define SO_RXQ_OVFL 40 | 32 #define SO_RXQ_OVFL 40 |
| 31 #endif | 33 #endif |
| 32 | 34 |
| 33 // TODO(rtenneti): Add support for MMSG_MORE. | 35 // TODO(rtenneti): Add support for MMSG_MORE. |
| 34 #define MMSG_MORE 0 | 36 #define MMSG_MORE 0 |
| 35 | 37 |
| 36 using base::StringPiece; | 38 using base::StringPiece; |
| 39 using base::StringToInt; |
| 37 using std::string; | 40 using std::string; |
| 38 using std::vector; | 41 using std::vector; |
| 39 | 42 |
| 40 namespace net { | 43 namespace net { |
| 41 | 44 |
| 42 const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET; | 45 const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET; |
| 43 | 46 |
| 44 void QuicClient::ClientQuicDataToResend::Resend() { | 47 void QuicClient::ClientQuicDataToResend::Resend() { |
| 45 client_->SendRequest(*headers_, body_, fin_); | 48 client_->SendRequest(*headers_, body_, fin_); |
| 46 delete headers_; | |
| 47 headers_ = nullptr; | 49 headers_ = nullptr; |
| 48 } | 50 } |
| 49 | 51 |
| 50 QuicClient::QuicClient(IPEndPoint server_address, | 52 QuicClient::QuicClient(IPEndPoint server_address, |
| 51 const QuicServerId& server_id, | 53 const QuicServerId& server_id, |
| 52 const QuicVersionVector& supported_versions, | 54 const QuicVersionVector& supported_versions, |
| 53 EpollServer* epoll_server, | 55 EpollServer* epoll_server, |
| 54 std::unique_ptr<ProofVerifier> proof_verifier) | 56 std::unique_ptr<ProofVerifier> proof_verifier) |
| 55 : QuicClient(server_address, | 57 : QuicClient(server_address, |
| 56 server_id, | 58 server_id, |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 | 119 |
| 118 if (!CreateUDPSocketAndBind()) { | 120 if (!CreateUDPSocketAndBind()) { |
| 119 return false; | 121 return false; |
| 120 } | 122 } |
| 121 | 123 |
| 122 epoll_server_->RegisterFD(GetLatestFD(), this, kEpollFlags); | 124 epoll_server_->RegisterFD(GetLatestFD(), this, kEpollFlags); |
| 123 initialized_ = true; | 125 initialized_ = true; |
| 124 return true; | 126 return true; |
| 125 } | 127 } |
| 126 | 128 |
| 127 QuicClient::QuicDataToResend::QuicDataToResend(BalsaHeaders* headers, | |
| 128 StringPiece body, | |
| 129 bool fin) | |
| 130 : headers_(headers), body_(body), fin_(fin) {} | |
| 131 | |
| 132 QuicClient::QuicDataToResend::~QuicDataToResend() { | |
| 133 if (headers_) { | |
| 134 delete headers_; | |
| 135 } | |
| 136 } | |
| 137 | |
| 138 bool QuicClient::CreateUDPSocketAndBind() { | 129 bool QuicClient::CreateUDPSocketAndBind() { |
| 139 int fd = | 130 int fd = |
| 140 QuicSocketUtils::CreateUDPSocket(server_address_, &overflow_supported_); | 131 QuicSocketUtils::CreateUDPSocket(server_address_, &overflow_supported_); |
| 141 if (fd < 0) { | 132 if (fd < 0) { |
| 142 return false; | 133 return false; |
| 143 } | 134 } |
| 144 | 135 |
| 145 IPEndPoint client_address; | 136 IPEndPoint client_address; |
| 146 if (bind_to_address_.size() != 0) { | 137 if (bind_to_address_.size() != 0) { |
| 147 client_address = IPEndPoint(bind_to_address_, local_port_); | 138 client_address = IPEndPoint(bind_to_address_, local_port_); |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 267 } | 258 } |
| 268 | 259 |
| 269 void QuicClient::CleanUpUDPSocketImpl(int fd) { | 260 void QuicClient::CleanUpUDPSocketImpl(int fd) { |
| 270 if (fd > -1) { | 261 if (fd > -1) { |
| 271 epoll_server_->UnregisterFD(fd); | 262 epoll_server_->UnregisterFD(fd); |
| 272 int rc = close(fd); | 263 int rc = close(fd); |
| 273 DCHECK_EQ(0, rc); | 264 DCHECK_EQ(0, rc); |
| 274 } | 265 } |
| 275 } | 266 } |
| 276 | 267 |
| 277 void QuicClient::SendRequest(const BalsaHeaders& headers, | 268 void QuicClient::SendRequest(const SpdyHeaderBlock& headers, |
| 278 StringPiece body, | 269 StringPiece body, |
| 279 bool fin) { | 270 bool fin) { |
| 280 QuicClientPushPromiseIndex::TryHandle* handle; | 271 QuicClientPushPromiseIndex::TryHandle* handle; |
| 281 QuicAsyncStatus rv = push_promise_index()->Try( | 272 QuicAsyncStatus rv = push_promise_index()->Try(headers, this, &handle); |
| 282 SpdyBalsaUtils::RequestHeadersToSpdyHeaders(headers), this, &handle); | |
| 283 if (rv == QUIC_SUCCESS) | 273 if (rv == QUIC_SUCCESS) |
| 284 return; | 274 return; |
| 285 | 275 |
| 286 if (rv == QUIC_PENDING) { | 276 if (rv == QUIC_PENDING) { |
| 287 // May need to retry request if asynchronous rendezvous fails. | 277 // May need to retry request if asynchronous rendezvous fails. |
| 288 auto* new_headers = new BalsaHeaders; | 278 std::unique_ptr<SpdyHeaderBlock> new_headers( |
| 289 new_headers->CopyFrom(headers); | 279 new SpdyHeaderBlock(headers.Clone())); |
| 290 push_promise_data_to_resend_.reset( | 280 push_promise_data_to_resend_.reset( |
| 291 new ClientQuicDataToResend(new_headers, body, fin, this)); | 281 new ClientQuicDataToResend(std::move(new_headers), body, fin, this)); |
| 292 return; | 282 return; |
| 293 } | 283 } |
| 294 | 284 |
| 295 QuicSpdyClientStream* stream = CreateReliableClientStream(); | 285 QuicSpdyClientStream* stream = CreateReliableClientStream(); |
| 296 if (stream == nullptr) { | 286 if (stream == nullptr) { |
| 297 QUIC_BUG << "stream creation failed!"; | 287 QUIC_BUG << "stream creation failed!"; |
| 298 return; | 288 return; |
| 299 } | 289 } |
| 300 stream->SendRequest(SpdyBalsaUtils::RequestHeadersToSpdyHeaders(headers), | 290 stream->SendRequest(headers.Clone(), body, fin); |
| 301 body, fin); | |
| 302 if (FLAGS_enable_quic_stateless_reject_support) { | 291 if (FLAGS_enable_quic_stateless_reject_support) { |
| 303 // Record this in case we need to resend. | 292 // Record this in case we need to resend. |
| 304 auto* new_headers = new BalsaHeaders; | 293 std::unique_ptr<SpdyHeaderBlock> new_headers( |
| 305 new_headers->CopyFrom(headers); | 294 new SpdyHeaderBlock(headers.Clone())); |
| 306 auto* data_to_resend = | 295 auto data_to_resend = |
| 307 new ClientQuicDataToResend(new_headers, body, fin, this); | 296 new ClientQuicDataToResend(std::move(new_headers), body, fin, this); |
| 308 MaybeAddQuicDataToResend(std::unique_ptr<QuicDataToResend>(data_to_resend)); | 297 MaybeAddQuicDataToResend(std::unique_ptr<QuicDataToResend>(data_to_resend)); |
| 309 } | 298 } |
| 310 } | 299 } |
| 311 | 300 |
| 312 void QuicClient::MaybeAddQuicDataToResend( | 301 void QuicClient::MaybeAddQuicDataToResend( |
| 313 std::unique_ptr<QuicDataToResend> data_to_resend) { | 302 std::unique_ptr<QuicDataToResend> data_to_resend) { |
| 314 DCHECK(FLAGS_enable_quic_stateless_reject_support); | 303 DCHECK(FLAGS_enable_quic_stateless_reject_support); |
| 315 if (session()->IsCryptoHandshakeConfirmed()) { | 304 if (session()->IsCryptoHandshakeConfirmed()) { |
| 316 // The handshake is confirmed. No need to continue saving requests to | 305 // The handshake is confirmed. No need to continue saving requests to |
| 317 // resend. | 306 // resend. |
| 318 data_to_resend_on_connect_.clear(); | 307 data_to_resend_on_connect_.clear(); |
| 319 return; | 308 return; |
| 320 } | 309 } |
| 321 | 310 |
| 322 // The handshake is not confirmed. Push the data onto the queue of data to | 311 // The handshake is not confirmed. Push the data onto the queue of data to |
| 323 // resend if statelessly rejected. | 312 // resend if statelessly rejected. |
| 324 data_to_resend_on_connect_.push_back(std::move(data_to_resend)); | 313 data_to_resend_on_connect_.push_back(std::move(data_to_resend)); |
| 325 } | 314 } |
| 326 | 315 |
| 327 void QuicClient::SendRequestAndWaitForResponse(const BalsaHeaders& headers, | 316 void QuicClient::SendRequestAndWaitForResponse(const SpdyHeaderBlock& headers, |
| 328 StringPiece body, | 317 StringPiece body, |
| 329 bool fin) { | 318 bool fin) { |
| 330 SendRequest(headers, body, fin); | 319 SendRequest(headers, body, fin); |
| 331 while (WaitForEvents()) { | 320 while (WaitForEvents()) { |
| 332 } | 321 } |
| 333 } | 322 } |
| 334 | 323 |
| 335 void QuicClient::SendRequestsAndWaitForResponse( | 324 void QuicClient::SendRequestsAndWaitForResponse( |
| 336 const vector<string>& url_list) { | 325 const vector<string>& url_list) { |
| 337 for (size_t i = 0; i < url_list.size(); ++i) { | 326 for (size_t i = 0; i < url_list.size(); ++i) { |
| 338 BalsaHeaders headers; | 327 SpdyHeaderBlock headers; |
| 339 headers.SetRequestFirstlineFromStringPieces("GET", url_list[i], "HTTP/1.1"); | 328 if (!SpdyUtils::PopulateHeaderBlockFromUrl(url_list[i], &headers)) { |
| 329 QUIC_BUG << "Unable to create request"; |
| 330 continue; |
| 331 } |
| 340 SendRequest(headers, "", true); | 332 SendRequest(headers, "", true); |
| 341 } | 333 } |
| 342 while (WaitForEvents()) { | 334 while (WaitForEvents()) { |
| 343 } | 335 } |
| 344 } | 336 } |
| 345 | 337 |
| 346 QuicSpdyClientStream* QuicClient::CreateReliableClientStream() { | 338 QuicSpdyClientStream* QuicClient::CreateReliableClientStream() { |
| 347 QuicSpdyClientStream* stream = QuicClientBase::CreateReliableClientStream(); | 339 QuicSpdyClientStream* stream = QuicClientBase::CreateReliableClientStream(); |
| 348 if (stream) { | 340 if (stream) { |
| 349 stream->set_visitor(this); | 341 stream->set_visitor(this); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 } | 401 } |
| 410 if (event->in_events & EPOLLERR) { | 402 if (event->in_events & EPOLLERR) { |
| 411 DVLOG(1) << "Epollerr"; | 403 DVLOG(1) << "Epollerr"; |
| 412 } | 404 } |
| 413 } | 405 } |
| 414 | 406 |
| 415 void QuicClient::OnClose(QuicSpdyStream* stream) { | 407 void QuicClient::OnClose(QuicSpdyStream* stream) { |
| 416 DCHECK(stream != nullptr); | 408 DCHECK(stream != nullptr); |
| 417 QuicSpdyClientStream* client_stream = | 409 QuicSpdyClientStream* client_stream = |
| 418 static_cast<QuicSpdyClientStream*>(stream); | 410 static_cast<QuicSpdyClientStream*>(stream); |
| 419 BalsaHeaders response_headers; | |
| 420 SpdyBalsaUtils::SpdyHeadersToResponseHeaders( | |
| 421 client_stream->response_headers(), &response_headers); | |
| 422 | 411 |
| 412 const SpdyHeaderBlock& response_headers = client_stream->response_headers(); |
| 423 if (response_listener_.get() != nullptr) { | 413 if (response_listener_.get() != nullptr) { |
| 424 response_listener_->OnCompleteResponse(stream->id(), response_headers, | 414 response_listener_->OnCompleteResponse(stream->id(), response_headers, |
| 425 client_stream->data()); | 415 client_stream->data()); |
| 426 } | 416 } |
| 427 | 417 |
| 428 // Store response headers and body. | 418 // Store response headers and body. |
| 429 if (store_response_) { | 419 if (store_response_) { |
| 430 latest_response_code_ = response_headers.parsed_response_code(); | 420 auto status = response_headers.find(":status"); |
| 431 response_headers.DumpHeadersToString(&latest_response_headers_); | 421 if (status == response_headers.end() || |
| 422 !StringToInt(status->second, &latest_response_code_)) { |
| 423 LOG(ERROR) << "Invalid response headers: no status code"; |
| 424 } |
| 425 latest_response_headers_ = response_headers.DebugString(); |
| 426 latest_response_header_block_ = response_headers.Clone(); |
| 432 latest_response_body_ = client_stream->data(); | 427 latest_response_body_ = client_stream->data(); |
| 433 latest_response_trailers_ = | 428 latest_response_trailers_ = |
| 434 client_stream->received_trailers().DebugString(); | 429 client_stream->received_trailers().DebugString(); |
| 435 } | 430 } |
| 436 } | 431 } |
| 437 | 432 |
| 438 bool QuicClient::CheckVary(const SpdyHeaderBlock& client_request, | 433 bool QuicClient::CheckVary(const SpdyHeaderBlock& client_request, |
| 439 const SpdyHeaderBlock& promise_request, | 434 const SpdyHeaderBlock& promise_request, |
| 440 const SpdyHeaderBlock& promise_response) { | 435 const SpdyHeaderBlock& promise_response) { |
| 441 return true; | 436 return true; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 455 size_t QuicClient::latest_response_code() const { | 450 size_t QuicClient::latest_response_code() const { |
| 456 QUIC_BUG_IF(!store_response_) << "Response not stored!"; | 451 QUIC_BUG_IF(!store_response_) << "Response not stored!"; |
| 457 return latest_response_code_; | 452 return latest_response_code_; |
| 458 } | 453 } |
| 459 | 454 |
| 460 const string& QuicClient::latest_response_headers() const { | 455 const string& QuicClient::latest_response_headers() const { |
| 461 QUIC_BUG_IF(!store_response_) << "Response not stored!"; | 456 QUIC_BUG_IF(!store_response_) << "Response not stored!"; |
| 462 return latest_response_headers_; | 457 return latest_response_headers_; |
| 463 } | 458 } |
| 464 | 459 |
| 460 const SpdyHeaderBlock& QuicClient::latest_response_header_block() const { |
| 461 QUIC_BUG_IF(!store_response_) << "Response not stored!"; |
| 462 return latest_response_header_block_; |
| 463 } |
| 464 |
| 465 const string& QuicClient::latest_response_body() const { | 465 const string& QuicClient::latest_response_body() const { |
| 466 QUIC_BUG_IF(!store_response_) << "Response not stored!"; | 466 QUIC_BUG_IF(!store_response_) << "Response not stored!"; |
| 467 return latest_response_body_; | 467 return latest_response_body_; |
| 468 } | 468 } |
| 469 | 469 |
| 470 const string& QuicClient::latest_response_trailers() const { | 470 const string& QuicClient::latest_response_trailers() const { |
| 471 QUIC_BUG_IF(!store_response_) << "Response not stored!"; | 471 QUIC_BUG_IF(!store_response_) << "Response not stored!"; |
| 472 return latest_response_trailers_; | 472 return latest_response_trailers_; |
| 473 } | 473 } |
| 474 | 474 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 492 return fd_address_map_.back().first; | 492 return fd_address_map_.back().first; |
| 493 } | 493 } |
| 494 | 494 |
| 495 void QuicClient::ProcessPacket(const IPEndPoint& self_address, | 495 void QuicClient::ProcessPacket(const IPEndPoint& self_address, |
| 496 const IPEndPoint& peer_address, | 496 const IPEndPoint& peer_address, |
| 497 const QuicReceivedPacket& packet) { | 497 const QuicReceivedPacket& packet) { |
| 498 session()->connection()->ProcessUdpPacket(self_address, peer_address, packet); | 498 session()->connection()->ProcessUdpPacket(self_address, peer_address, packet); |
| 499 } | 499 } |
| 500 | 500 |
| 501 } // namespace net | 501 } // namespace net |
| OLD | NEW |