| 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> |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 const QuicConfig& config, | 62 const QuicConfig& config, |
| 63 EpollServer* epoll_server, | 63 EpollServer* epoll_server, |
| 64 std::unique_ptr<ProofVerifier> proof_verifier) | 64 std::unique_ptr<ProofVerifier> proof_verifier) |
| 65 : QuicClientBase( | 65 : QuicClientBase( |
| 66 server_id, | 66 server_id, |
| 67 supported_versions, | 67 supported_versions, |
| 68 config, | 68 config, |
| 69 new QuicEpollConnectionHelper(epoll_server, QuicAllocator::SIMPLE), | 69 new QuicEpollConnectionHelper(epoll_server, QuicAllocator::SIMPLE), |
| 70 new QuicEpollAlarmFactory(epoll_server), | 70 new QuicEpollAlarmFactory(epoll_server), |
| 71 std::move(proof_verifier)), | 71 std::move(proof_verifier)), |
| 72 server_address_(server_address), | |
| 73 local_port_(0), | |
| 74 epoll_server_(epoll_server), | 72 epoll_server_(epoll_server), |
| 75 initialized_(false), | 73 initialized_(false), |
| 76 packets_dropped_(0), | 74 packets_dropped_(0), |
| 77 overflow_supported_(false), | 75 overflow_supported_(false), |
| 78 store_response_(false), | 76 packet_reader_(new QuicPacketReader()) { |
| 79 latest_response_code_(-1), | 77 set_server_address(server_address); |
| 80 packet_reader_(new QuicPacketReader()) {} | 78 } |
| 81 | 79 |
| 82 QuicClient::~QuicClient() { | 80 QuicClient::~QuicClient() { |
| 83 if (connected()) { | 81 if (connected()) { |
| 84 session()->connection()->CloseConnection( | 82 session()->connection()->CloseConnection( |
| 85 QUIC_PEER_GOING_AWAY, "Client being torn down", | 83 QUIC_PEER_GOING_AWAY, "Client being torn down", |
| 86 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); | 84 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); |
| 87 } | 85 } |
| 88 | 86 |
| 89 CleanUpAllUDPSockets(); | 87 CleanUpAllUDPSockets(); |
| 90 } | 88 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 116 return false; | 114 return false; |
| 117 } | 115 } |
| 118 | 116 |
| 119 epoll_server_->RegisterFD(GetLatestFD(), this, kEpollFlags); | 117 epoll_server_->RegisterFD(GetLatestFD(), this, kEpollFlags); |
| 120 initialized_ = true; | 118 initialized_ = true; |
| 121 return true; | 119 return true; |
| 122 } | 120 } |
| 123 | 121 |
| 124 bool QuicClient::CreateUDPSocketAndBind() { | 122 bool QuicClient::CreateUDPSocketAndBind() { |
| 125 int fd = | 123 int fd = |
| 126 QuicSocketUtils::CreateUDPSocket(server_address_, &overflow_supported_); | 124 QuicSocketUtils::CreateUDPSocket(server_address(), &overflow_supported_); |
| 127 if (fd < 0) { | 125 if (fd < 0) { |
| 128 return false; | 126 return false; |
| 129 } | 127 } |
| 130 | 128 |
| 131 IPEndPoint client_address; | 129 IPEndPoint client_address; |
| 132 if (bind_to_address_.size() != 0) { | 130 if (bind_to_address().size() != 0) { |
| 133 client_address = IPEndPoint(bind_to_address_, local_port_); | 131 client_address = IPEndPoint(bind_to_address(), local_port()); |
| 134 } else if (server_address_.GetSockAddrFamily() == AF_INET) { | 132 } else if (server_address().GetSockAddrFamily() == AF_INET) { |
| 135 client_address = IPEndPoint(IPAddress::IPv4AllZeros(), local_port_); | 133 client_address = IPEndPoint(IPAddress::IPv4AllZeros(), local_port()); |
| 136 } else { | 134 } else { |
| 137 IPAddress any6 = IPAddress::IPv6AllZeros(); | 135 IPAddress any6 = IPAddress::IPv6AllZeros(); |
| 138 client_address = IPEndPoint(any6, local_port_); | 136 client_address = IPEndPoint(any6, local_port()); |
| 139 } | 137 } |
| 140 | 138 |
| 141 sockaddr_storage raw_addr; | 139 sockaddr_storage raw_addr; |
| 142 socklen_t raw_addr_len = sizeof(raw_addr); | 140 socklen_t raw_addr_len = sizeof(raw_addr); |
| 143 CHECK(client_address.ToSockAddr(reinterpret_cast<sockaddr*>(&raw_addr), | 141 CHECK(client_address.ToSockAddr(reinterpret_cast<sockaddr*>(&raw_addr), |
| 144 &raw_addr_len)); | 142 &raw_addr_len)); |
| 145 int rc = | 143 int rc = |
| 146 bind(fd, reinterpret_cast<const sockaddr*>(&raw_addr), sizeof(raw_addr)); | 144 bind(fd, reinterpret_cast<const sockaddr*>(&raw_addr), sizeof(raw_addr)); |
| 147 if (rc < 0) { | 145 if (rc < 0) { |
| 148 LOG(ERROR) << "Bind failed: " << strerror(errno); | 146 LOG(ERROR) << "Bind failed: " << strerror(errno); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 // does not need to be resent. | 199 // does not need to be resent. |
| 202 if (session()->error() != QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { | 200 if (session()->error() != QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { |
| 203 ClearDataToResend(); | 201 ClearDataToResend(); |
| 204 } | 202 } |
| 205 // Before we destroy the last session and create a new one, gather its stats | 203 // Before we destroy the last session and create a new one, gather its stats |
| 206 // and update the stats for the overall connection. | 204 // and update the stats for the overall connection. |
| 207 UpdateStats(); | 205 UpdateStats(); |
| 208 } | 206 } |
| 209 | 207 |
| 210 CreateQuicClientSession(new QuicConnection( | 208 CreateQuicClientSession(new QuicConnection( |
| 211 GetNextConnectionId(), server_address_, helper(), alarm_factory(), writer, | 209 GetNextConnectionId(), server_address(), helper(), alarm_factory(), |
| 210 writer, |
| 212 /* owns_writer= */ false, Perspective::IS_CLIENT, supported_versions())); | 211 /* owns_writer= */ false, Perspective::IS_CLIENT, supported_versions())); |
| 213 | 212 |
| 214 // Reset |writer()| after |session()| so that the old writer outlives the old | 213 // Reset |writer()| after |session()| so that the old writer outlives the old |
| 215 // session. | 214 // session. |
| 216 set_writer(writer); | 215 set_writer(writer); |
| 217 session()->Initialize(); | 216 session()->Initialize(); |
| 218 session()->CryptoConnect(); | 217 session()->CryptoConnect(); |
| 219 set_connected_or_attempting_connect(true); | 218 set_connected_or_attempting_connect(true); |
| 220 } | 219 } |
| 221 | 220 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 294 if (!SpdyUtils::PopulateHeaderBlockFromUrl(url_list[i], &headers)) { | 293 if (!SpdyUtils::PopulateHeaderBlockFromUrl(url_list[i], &headers)) { |
| 295 QUIC_BUG << "Unable to create request"; | 294 QUIC_BUG << "Unable to create request"; |
| 296 continue; | 295 continue; |
| 297 } | 296 } |
| 298 SendRequest(headers, "", true); | 297 SendRequest(headers, "", true); |
| 299 } | 298 } |
| 300 while (WaitForEvents()) { | 299 while (WaitForEvents()) { |
| 301 } | 300 } |
| 302 } | 301 } |
| 303 | 302 |
| 304 QuicSpdyClientStream* QuicClient::CreateReliableClientStream() { | |
| 305 QuicSpdyClientStream* stream = QuicClientBase::CreateReliableClientStream(); | |
| 306 if (stream) { | |
| 307 stream->set_visitor(this); | |
| 308 } | |
| 309 return stream; | |
| 310 } | |
| 311 | |
| 312 bool QuicClient::WaitForEvents() { | 303 bool QuicClient::WaitForEvents() { |
| 313 DCHECK(connected()); | 304 DCHECK(connected()); |
| 314 | 305 |
| 315 epoll_server_->WaitForEventsAndExecuteCallbacks(); | 306 epoll_server_->WaitForEventsAndExecuteCallbacks(); |
| 316 base::RunLoop().RunUntilIdle(); | 307 base::RunLoop().RunUntilIdle(); |
| 317 | 308 |
| 318 DCHECK(session() != nullptr); | 309 DCHECK(session() != nullptr); |
| 319 if (!connected() && | 310 if (!connected() && |
| 320 session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { | 311 session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { |
| 321 DCHECK(FLAGS_enable_quic_stateless_reject_support); | 312 DCHECK(FLAGS_enable_quic_stateless_reject_support); |
| 322 DVLOG(1) << "Detected stateless reject while waiting for events. " | 313 DVLOG(1) << "Detected stateless reject while waiting for events. " |
| 323 << "Attempting to reconnect."; | 314 << "Attempting to reconnect."; |
| 324 Connect(); | 315 Connect(); |
| 325 } | 316 } |
| 326 | 317 |
| 327 return session()->num_active_requests() != 0; | 318 return session()->num_active_requests() != 0; |
| 328 } | 319 } |
| 329 | 320 |
| 330 bool QuicClient::MigrateSocket(const IPAddress& new_host) { | 321 bool QuicClient::MigrateSocket(const IPAddress& new_host) { |
| 331 if (!connected()) { | 322 if (!connected()) { |
| 332 return false; | 323 return false; |
| 333 } | 324 } |
| 334 | 325 |
| 335 CleanUpUDPSocket(GetLatestFD()); | 326 CleanUpUDPSocket(GetLatestFD()); |
| 336 | 327 |
| 337 bind_to_address_ = new_host; | 328 set_bind_to_address(new_host); |
| 338 if (!CreateUDPSocketAndBind()) { | 329 if (!CreateUDPSocketAndBind()) { |
| 339 return false; | 330 return false; |
| 340 } | 331 } |
| 341 | 332 |
| 342 epoll_server_->RegisterFD(GetLatestFD(), this, kEpollFlags); | 333 epoll_server_->RegisterFD(GetLatestFD(), this, kEpollFlags); |
| 343 session()->connection()->SetSelfAddress(GetLatestClientAddress()); | 334 session()->connection()->SetSelfAddress(GetLatestClientAddress()); |
| 344 | 335 |
| 345 QuicPacketWriter* writer = CreateQuicPacketWriter(); | 336 QuicPacketWriter* writer = CreateQuicPacketWriter(); |
| 346 set_writer(writer); | 337 set_writer(writer); |
| 347 session()->connection()->SetQuicPacketWriter(writer, false); | 338 session()->connection()->SetQuicPacketWriter(writer, false); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 363 } | 354 } |
| 364 if (connected() && (event->in_events & EPOLLOUT)) { | 355 if (connected() && (event->in_events & EPOLLOUT)) { |
| 365 writer()->SetWritable(); | 356 writer()->SetWritable(); |
| 366 session()->connection()->OnCanWrite(); | 357 session()->connection()->OnCanWrite(); |
| 367 } | 358 } |
| 368 if (event->in_events & EPOLLERR) { | 359 if (event->in_events & EPOLLERR) { |
| 369 DVLOG(1) << "Epollerr"; | 360 DVLOG(1) << "Epollerr"; |
| 370 } | 361 } |
| 371 } | 362 } |
| 372 | 363 |
| 373 void QuicClient::OnClose(QuicSpdyStream* stream) { | |
| 374 DCHECK(stream != nullptr); | |
| 375 QuicSpdyClientStream* client_stream = | |
| 376 static_cast<QuicSpdyClientStream*>(stream); | |
| 377 | |
| 378 const SpdyHeaderBlock& response_headers = client_stream->response_headers(); | |
| 379 if (response_listener_.get() != nullptr) { | |
| 380 response_listener_->OnCompleteResponse(stream->id(), response_headers, | |
| 381 client_stream->data()); | |
| 382 } | |
| 383 | |
| 384 // Store response headers and body. | |
| 385 if (store_response_) { | |
| 386 auto status = response_headers.find(":status"); | |
| 387 if (status == response_headers.end() || | |
| 388 !StringToInt(status->second, &latest_response_code_)) { | |
| 389 LOG(ERROR) << "Invalid response headers: no status code"; | |
| 390 } | |
| 391 latest_response_headers_ = response_headers.DebugString(); | |
| 392 latest_response_header_block_ = response_headers.Clone(); | |
| 393 latest_response_body_ = client_stream->data(); | |
| 394 latest_response_trailers_ = | |
| 395 client_stream->received_trailers().DebugString(); | |
| 396 } | |
| 397 } | |
| 398 | |
| 399 size_t QuicClient::latest_response_code() const { | |
| 400 QUIC_BUG_IF(!store_response_) << "Response not stored!"; | |
| 401 return latest_response_code_; | |
| 402 } | |
| 403 | |
| 404 const string& QuicClient::latest_response_headers() const { | |
| 405 QUIC_BUG_IF(!store_response_) << "Response not stored!"; | |
| 406 return latest_response_headers_; | |
| 407 } | |
| 408 | |
| 409 const SpdyHeaderBlock& QuicClient::latest_response_header_block() const { | |
| 410 QUIC_BUG_IF(!store_response_) << "Response not stored!"; | |
| 411 return latest_response_header_block_; | |
| 412 } | |
| 413 | |
| 414 const string& QuicClient::latest_response_body() const { | |
| 415 QUIC_BUG_IF(!store_response_) << "Response not stored!"; | |
| 416 return latest_response_body_; | |
| 417 } | |
| 418 | |
| 419 const string& QuicClient::latest_response_trailers() const { | |
| 420 QUIC_BUG_IF(!store_response_) << "Response not stored!"; | |
| 421 return latest_response_trailers_; | |
| 422 } | |
| 423 | |
| 424 QuicPacketWriter* QuicClient::CreateQuicPacketWriter() { | 364 QuicPacketWriter* QuicClient::CreateQuicPacketWriter() { |
| 425 return new QuicDefaultPacketWriter(GetLatestFD()); | 365 return new QuicDefaultPacketWriter(GetLatestFD()); |
| 426 } | 366 } |
| 427 | 367 |
| 428 const IPEndPoint QuicClient::GetLatestClientAddress() const { | 368 const IPEndPoint QuicClient::GetLatestClientAddress() const { |
| 429 if (fd_address_map_.empty()) { | 369 if (fd_address_map_.empty()) { |
| 430 return IPEndPoint(); | 370 return IPEndPoint(); |
| 431 } | 371 } |
| 432 | 372 |
| 433 return fd_address_map_.back().second; | 373 return fd_address_map_.back().second; |
| 434 } | 374 } |
| 435 | 375 |
| 436 int QuicClient::GetLatestFD() const { | 376 int QuicClient::GetLatestFD() const { |
| 437 if (fd_address_map_.empty()) { | 377 if (fd_address_map_.empty()) { |
| 438 return -1; | 378 return -1; |
| 439 } | 379 } |
| 440 | 380 |
| 441 return fd_address_map_.back().first; | 381 return fd_address_map_.back().first; |
| 442 } | 382 } |
| 443 | 383 |
| 444 void QuicClient::ProcessPacket(const IPEndPoint& self_address, | 384 void QuicClient::ProcessPacket(const IPEndPoint& self_address, |
| 445 const IPEndPoint& peer_address, | 385 const IPEndPoint& peer_address, |
| 446 const QuicReceivedPacket& packet) { | 386 const QuicReceivedPacket& packet) { |
| 447 session()->connection()->ProcessUdpPacket(self_address, peer_address, packet); | 387 session()->connection()->ProcessUdpPacket(self_address, peer_address, packet); |
| 448 } | 388 } |
| 449 | 389 |
| 450 } // namespace net | 390 } // namespace net |
| OLD | NEW |