| 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 <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/run_loop.h" | 10 #include "base/run_loop.h" |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 #include "net/spdy/spdy_header_block.h" | 25 #include "net/spdy/spdy_header_block.h" |
| 26 #include "net/spdy/spdy_http_utils.h" | 26 #include "net/spdy/spdy_http_utils.h" |
| 27 #include "net/udp/udp_client_socket.h" | 27 #include "net/udp/udp_client_socket.h" |
| 28 | 28 |
| 29 using std::string; | 29 using std::string; |
| 30 using std::vector; | 30 using std::vector; |
| 31 using base::StringPiece; | 31 using base::StringPiece; |
| 32 | 32 |
| 33 namespace net { | 33 namespace net { |
| 34 | 34 |
| 35 void QuicSimpleClient::ClientQuicDataToResend::Resend() { | |
| 36 client_->SendRequest(*headers_, body_, fin_); | |
| 37 headers_ = nullptr; | |
| 38 } | |
| 39 | |
| 40 QuicSimpleClient::QuicSimpleClient( | 35 QuicSimpleClient::QuicSimpleClient( |
| 41 IPEndPoint server_address, | 36 IPEndPoint server_address, |
| 42 const QuicServerId& server_id, | 37 const QuicServerId& server_id, |
| 43 const QuicVersionVector& supported_versions, | 38 const QuicVersionVector& supported_versions, |
| 44 std::unique_ptr<ProofVerifier> proof_verifier) | 39 std::unique_ptr<ProofVerifier> proof_verifier) |
| 45 : QuicClientBase(server_id, | 40 : QuicClientBase(server_id, |
| 46 supported_versions, | 41 supported_versions, |
| 47 QuicConfig(), | 42 QuicConfig(), |
| 48 CreateQuicConnectionHelper(), | 43 CreateQuicConnectionHelper(), |
| 49 CreateQuicAlarmFactory(), | 44 CreateQuicAlarmFactory(), |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 bool QuicSimpleClient::Connect() { | 149 bool QuicSimpleClient::Connect() { |
| 155 // Attempt multiple connects until the maximum number of client hellos have | 150 // Attempt multiple connects until the maximum number of client hellos have |
| 156 // been sent. | 151 // been sent. |
| 157 while (!connected() && | 152 while (!connected() && |
| 158 GetNumSentClientHellos() <= QuicCryptoClientStream::kMaxClientHellos) { | 153 GetNumSentClientHellos() <= QuicCryptoClientStream::kMaxClientHellos) { |
| 159 StartConnect(); | 154 StartConnect(); |
| 160 StartPacketReaderIfNotStarted(); | 155 StartPacketReaderIfNotStarted(); |
| 161 while (EncryptionBeingEstablished()) { | 156 while (EncryptionBeingEstablished()) { |
| 162 WaitForEvents(); | 157 WaitForEvents(); |
| 163 } | 158 } |
| 164 if (FLAGS_enable_quic_stateless_reject_support && connected() && | 159 if (FLAGS_enable_quic_stateless_reject_support && connected()) { |
| 165 !data_to_resend_on_connect_.empty()) { | 160 // Resend any previously queued data. |
| 166 // A connection has been established and there was previously queued data | 161 ResendSavedData(); |
| 167 // to resend. Resend it and empty the queue. | |
| 168 std::vector<std::unique_ptr<QuicDataToResend>> old_data; | |
| 169 old_data.swap(data_to_resend_on_connect_); | |
| 170 for (const auto& data : old_data) { | |
| 171 data->Resend(); | |
| 172 } | |
| 173 data_to_resend_on_connect_.clear(); | |
| 174 } | 162 } |
| 175 if (session() != nullptr && | 163 if (session() != nullptr && |
| 176 session()->error() != QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { | 164 session()->error() != QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { |
| 177 // We've successfully created a session but we're not connected, and there | 165 // We've successfully created a session but we're not connected, and there |
| 178 // is no stateless reject to recover from. Give up trying. | 166 // is no stateless reject to recover from. Give up trying. |
| 179 break; | 167 break; |
| 180 } | 168 } |
| 181 } | 169 } |
| 182 if (!connected() && | 170 if (!connected() && |
| 183 GetNumSentClientHellos() > QuicCryptoClientStream::kMaxClientHellos && | 171 GetNumSentClientHellos() > QuicCryptoClientStream::kMaxClientHellos && |
| 184 session() != nullptr && | 172 session() != nullptr && |
| 185 session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { | 173 session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { |
| 186 // The overall connection failed due too many stateless rejects. | 174 // The overall connection failed due too many stateless rejects. |
| 187 set_connection_error(QUIC_CRYPTO_TOO_MANY_REJECTS); | 175 set_connection_error(QUIC_CRYPTO_TOO_MANY_REJECTS); |
| 188 } | 176 } |
| 189 return session()->connection()->connected(); | 177 return session()->connection()->connected(); |
| 190 } | 178 } |
| 191 | 179 |
| 192 void QuicSimpleClient::StartConnect() { | 180 void QuicSimpleClient::StartConnect() { |
| 193 DCHECK(initialized_); | 181 DCHECK(initialized_); |
| 194 DCHECK(!connected()); | 182 DCHECK(!connected()); |
| 195 | 183 |
| 196 set_writer(CreateQuicPacketWriter()); | 184 set_writer(CreateQuicPacketWriter()); |
| 197 | 185 |
| 198 if (connected_or_attempting_connect()) { | 186 if (connected_or_attempting_connect()) { |
| 199 // If the last error was not a stateless reject, then the queued up data | 187 // If the last error was not a stateless reject, then the queued up data |
| 200 // does not need to be resent. | 188 // does not need to be resent. |
| 201 if (session()->error() != QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { | 189 if (session()->error() != QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { |
| 202 data_to_resend_on_connect_.clear(); | 190 ClearDataToResend(); |
| 203 } | 191 } |
| 204 // Before we destroy the last session and create a new one, gather its stats | 192 // Before we destroy the last session and create a new one, gather its stats |
| 205 // and update the stats for the overall connection. | 193 // and update the stats for the overall connection. |
| 206 UpdateStats(); | 194 UpdateStats(); |
| 207 } | 195 } |
| 208 | 196 |
| 209 CreateQuicClientSession(new QuicConnection( | 197 CreateQuicClientSession(new QuicConnection( |
| 210 GetNextConnectionId(), server_address_, helper(), alarm_factory(), | 198 GetNextConnectionId(), server_address_, helper(), alarm_factory(), |
| 211 writer(), | 199 writer(), |
| 212 /* owns_writer= */ false, Perspective::IS_CLIENT, supported_versions())); | 200 /* owns_writer= */ false, Perspective::IS_CLIENT, supported_versions())); |
| 213 | 201 |
| 214 session()->Initialize(); | 202 session()->Initialize(); |
| 215 session()->CryptoConnect(); | 203 session()->CryptoConnect(); |
| 216 set_connected_or_attempting_connect(true); | 204 set_connected_or_attempting_connect(true); |
| 217 } | 205 } |
| 218 | 206 |
| 219 void QuicSimpleClient::Disconnect() { | 207 void QuicSimpleClient::Disconnect() { |
| 220 DCHECK(initialized_); | 208 DCHECK(initialized_); |
| 221 | 209 |
| 222 if (connected()) { | 210 if (connected()) { |
| 223 session()->connection()->CloseConnection( | 211 session()->connection()->CloseConnection( |
| 224 QUIC_PEER_GOING_AWAY, "Client disconnecting", | 212 QUIC_PEER_GOING_AWAY, "Client disconnecting", |
| 225 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); | 213 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); |
| 226 } | 214 } |
| 227 data_to_resend_on_connect_.clear(); | 215 ClearDataToResend(); |
| 228 | 216 |
| 229 reset_writer(); | 217 reset_writer(); |
| 230 packet_reader_.reset(); | 218 packet_reader_.reset(); |
| 231 packet_reader_started_ = false; | 219 packet_reader_started_ = false; |
| 232 | 220 |
| 233 initialized_ = false; | 221 initialized_ = false; |
| 234 } | 222 } |
| 235 | 223 |
| 236 void QuicSimpleClient::SendRequest(const SpdyHeaderBlock& headers, | 224 void QuicSimpleClient::SendRequest(const SpdyHeaderBlock& headers, |
| 237 StringPiece body, | 225 StringPiece body, |
| 238 bool fin) { | 226 bool fin) { |
| 227 QuicClientPushPromiseIndex::TryHandle* handle; |
| 228 QuicAsyncStatus rv = push_promise_index()->Try(headers, this, &handle); |
| 229 if (rv == QUIC_SUCCESS) |
| 230 return; |
| 231 |
| 232 if (rv == QUIC_PENDING) { |
| 233 // May need to retry request if asynchronous rendezvous fails. |
| 234 AddPromiseDataToResend(headers, body, fin); |
| 235 return; |
| 236 } |
| 237 |
| 239 QuicSpdyClientStream* stream = CreateReliableClientStream(); | 238 QuicSpdyClientStream* stream = CreateReliableClientStream(); |
| 240 if (stream == nullptr) { | 239 if (stream == nullptr) { |
| 241 LOG(DFATAL) << "stream creation failed!"; | 240 QUIC_BUG << "stream creation failed!"; |
| 242 return; | 241 return; |
| 243 } | 242 } |
| 244 stream->set_visitor(this); | 243 stream->set_visitor(this); |
| 245 stream->SendRequest(headers.Clone(), body, fin); | 244 stream->SendRequest(headers.Clone(), body, fin); |
| 246 if (FLAGS_enable_quic_stateless_reject_support) { | 245 // Record this in case we need to resend. |
| 247 // Record this in case we need to resend. | 246 MaybeAddDataToResend(headers, body, fin); |
| 248 std::unique_ptr<SpdyHeaderBlock> new_headers( | |
| 249 new SpdyHeaderBlock(headers.Clone())); | |
| 250 auto data_to_resend = | |
| 251 new ClientQuicDataToResend(std::move(new_headers), body, fin, this); | |
| 252 MaybeAddQuicDataToResend(std::unique_ptr<QuicDataToResend>(data_to_resend)); | |
| 253 } | |
| 254 } | |
| 255 | |
| 256 void QuicSimpleClient::MaybeAddQuicDataToResend( | |
| 257 std::unique_ptr<QuicDataToResend> data_to_resend) { | |
| 258 DCHECK(FLAGS_enable_quic_stateless_reject_support); | |
| 259 if (session()->IsCryptoHandshakeConfirmed()) { | |
| 260 // The handshake is confirmed. No need to continue saving requests to | |
| 261 // resend. | |
| 262 data_to_resend_on_connect_.clear(); | |
| 263 return; | |
| 264 } | |
| 265 | |
| 266 // The handshake is not confirmed. Push the data onto the queue of data to | |
| 267 // resend if statelessly rejected. | |
| 268 data_to_resend_on_connect_.push_back(std::move(data_to_resend)); | |
| 269 } | 247 } |
| 270 | 248 |
| 271 void QuicSimpleClient::SendRequestAndWaitForResponse( | 249 void QuicSimpleClient::SendRequestAndWaitForResponse( |
| 272 const SpdyHeaderBlock& headers, | 250 const SpdyHeaderBlock& headers, |
| 273 base::StringPiece body, | 251 base::StringPiece body, |
| 274 bool fin) { | 252 bool fin) { |
| 275 SendRequest(headers, body, fin); | 253 SendRequest(headers, body, fin); |
| 276 while (WaitForEvents()) { | 254 while (WaitForEvents()) { |
| 277 } | 255 } |
| 278 } | 256 } |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 392 session()->connection()->ProcessUdpPacket(local_address, peer_address, | 370 session()->connection()->ProcessUdpPacket(local_address, peer_address, |
| 393 packet); | 371 packet); |
| 394 if (!session()->connection()->connected()) { | 372 if (!session()->connection()->connected()) { |
| 395 return false; | 373 return false; |
| 396 } | 374 } |
| 397 | 375 |
| 398 return true; | 376 return true; |
| 399 } | 377 } |
| 400 | 378 |
| 401 } // namespace net | 379 } // namespace net |
| OLD | NEW |