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 |