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 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 } | 259 } |
269 | 260 |
270 void QuicClient::CleanUpUDPSocketImpl(int fd) { | 261 void QuicClient::CleanUpUDPSocketImpl(int fd) { |
271 if (fd > -1) { | 262 if (fd > -1) { |
272 epoll_server_->UnregisterFD(fd); | 263 epoll_server_->UnregisterFD(fd); |
273 int rc = close(fd); | 264 int rc = close(fd); |
274 DCHECK_EQ(0, rc); | 265 DCHECK_EQ(0, rc); |
275 } | 266 } |
276 } | 267 } |
277 | 268 |
278 void QuicClient::SendRequest(const BalsaHeaders& headers, | 269 void QuicClient::SendRequest(const SpdyHeaderBlock& headers, |
279 StringPiece body, | 270 StringPiece body, |
280 bool fin) { | 271 bool fin) { |
281 QuicClientPushPromiseIndex::TryHandle* handle; | 272 QuicClientPushPromiseIndex::TryHandle* handle; |
282 QuicAsyncStatus rv = push_promise_index()->Try( | 273 QuicAsyncStatus rv = push_promise_index()->Try(headers, this, &handle); |
283 SpdyBalsaUtils::RequestHeadersToSpdyHeaders(headers), this, &handle); | |
284 if (rv == QUIC_SUCCESS) | 274 if (rv == QUIC_SUCCESS) |
285 return; | 275 return; |
286 | 276 |
287 if (rv == QUIC_PENDING) { | 277 if (rv == QUIC_PENDING) { |
288 // May need to retry request if asynchronous rendezvous fails. | 278 // May need to retry request if asynchronous rendezvous fails. |
289 auto* new_headers = new BalsaHeaders; | 279 std::unique_ptr<SpdyHeaderBlock> new_headers( |
290 new_headers->CopyFrom(headers); | 280 new SpdyHeaderBlock(headers.Clone())); |
291 push_promise_data_to_resend_.reset( | 281 push_promise_data_to_resend_.reset( |
292 new ClientQuicDataToResend(new_headers, body, fin, this)); | 282 new ClientQuicDataToResend(std::move(new_headers), body, fin, this)); |
293 return; | 283 return; |
294 } | 284 } |
295 | 285 |
296 QuicSpdyClientStream* stream = CreateReliableClientStream(); | 286 QuicSpdyClientStream* stream = CreateReliableClientStream(); |
297 if (stream == nullptr) { | 287 if (stream == nullptr) { |
298 QUIC_BUG << "stream creation failed!"; | 288 QUIC_BUG << "stream creation failed!"; |
299 return; | 289 return; |
300 } | 290 } |
301 stream->SendRequest(SpdyBalsaUtils::RequestHeadersToSpdyHeaders(headers), | 291 stream->SendRequest(headers.Clone(), body, fin); |
302 body, fin); | |
303 if (FLAGS_enable_quic_stateless_reject_support) { | 292 if (FLAGS_enable_quic_stateless_reject_support) { |
304 // Record this in case we need to resend. | 293 // Record this in case we need to resend. |
305 auto* new_headers = new BalsaHeaders; | 294 std::unique_ptr<SpdyHeaderBlock> new_headers( |
306 new_headers->CopyFrom(headers); | 295 new SpdyHeaderBlock(headers.Clone())); |
307 auto* data_to_resend = | 296 auto data_to_resend = |
308 new ClientQuicDataToResend(new_headers, body, fin, this); | 297 new ClientQuicDataToResend(std::move(new_headers), body, fin, this); |
309 MaybeAddQuicDataToResend(std::unique_ptr<QuicDataToResend>(data_to_resend)); | 298 MaybeAddQuicDataToResend(std::unique_ptr<QuicDataToResend>(data_to_resend)); |
310 } | 299 } |
311 } | 300 } |
312 | 301 |
313 void QuicClient::MaybeAddQuicDataToResend( | 302 void QuicClient::MaybeAddQuicDataToResend( |
314 std::unique_ptr<QuicDataToResend> data_to_resend) { | 303 std::unique_ptr<QuicDataToResend> data_to_resend) { |
315 DCHECK(FLAGS_enable_quic_stateless_reject_support); | 304 DCHECK(FLAGS_enable_quic_stateless_reject_support); |
316 if (session()->IsCryptoHandshakeConfirmed()) { | 305 if (session()->IsCryptoHandshakeConfirmed()) { |
317 // The handshake is confirmed. No need to continue saving requests to | 306 // The handshake is confirmed. No need to continue saving requests to |
318 // resend. | 307 // resend. |
319 data_to_resend_on_connect_.clear(); | 308 data_to_resend_on_connect_.clear(); |
320 return; | 309 return; |
321 } | 310 } |
322 | 311 |
323 // The handshake is not confirmed. Push the data onto the queue of data to | 312 // The handshake is not confirmed. Push the data onto the queue of data to |
324 // resend if statelessly rejected. | 313 // resend if statelessly rejected. |
325 data_to_resend_on_connect_.push_back(std::move(data_to_resend)); | 314 data_to_resend_on_connect_.push_back(std::move(data_to_resend)); |
326 } | 315 } |
327 | 316 |
328 void QuicClient::SendRequestAndWaitForResponse(const BalsaHeaders& headers, | 317 void QuicClient::SendRequestAndWaitForResponse(const SpdyHeaderBlock& headers, |
329 StringPiece body, | 318 StringPiece body, |
330 bool fin) { | 319 bool fin) { |
331 SendRequest(headers, body, fin); | 320 SendRequest(headers, body, fin); |
332 while (WaitForEvents()) { | 321 while (WaitForEvents()) { |
333 } | 322 } |
334 } | 323 } |
335 | 324 |
336 void QuicClient::SendRequestsAndWaitForResponse( | 325 void QuicClient::SendRequestsAndWaitForResponse( |
337 const vector<string>& url_list) { | 326 const vector<string>& url_list) { |
338 for (size_t i = 0; i < url_list.size(); ++i) { | 327 for (size_t i = 0; i < url_list.size(); ++i) { |
339 BalsaHeaders headers; | 328 SpdyHeaderBlock headers; |
340 headers.SetRequestFirstlineFromStringPieces("GET", url_list[i], "HTTP/1.1"); | 329 if (!SpdyUtils::PopulateHeaderBlockFromUrl(url_list[i], &headers)) { |
| 330 QUIC_BUG << "Unable to create request"; |
| 331 continue; |
| 332 } |
341 SendRequest(headers, "", true); | 333 SendRequest(headers, "", true); |
342 } | 334 } |
343 while (WaitForEvents()) { | 335 while (WaitForEvents()) { |
344 } | 336 } |
345 } | 337 } |
346 | 338 |
347 QuicSpdyClientStream* QuicClient::CreateReliableClientStream() { | 339 QuicSpdyClientStream* QuicClient::CreateReliableClientStream() { |
348 QuicSpdyClientStream* stream = QuicClientBase::CreateReliableClientStream(); | 340 QuicSpdyClientStream* stream = QuicClientBase::CreateReliableClientStream(); |
349 if (stream) { | 341 if (stream) { |
350 stream->set_visitor(this); | 342 stream->set_visitor(this); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 } | 402 } |
411 if (event->in_events & EPOLLERR) { | 403 if (event->in_events & EPOLLERR) { |
412 DVLOG(1) << "Epollerr"; | 404 DVLOG(1) << "Epollerr"; |
413 } | 405 } |
414 } | 406 } |
415 | 407 |
416 void QuicClient::OnClose(QuicSpdyStream* stream) { | 408 void QuicClient::OnClose(QuicSpdyStream* stream) { |
417 DCHECK(stream != nullptr); | 409 DCHECK(stream != nullptr); |
418 QuicSpdyClientStream* client_stream = | 410 QuicSpdyClientStream* client_stream = |
419 static_cast<QuicSpdyClientStream*>(stream); | 411 static_cast<QuicSpdyClientStream*>(stream); |
420 BalsaHeaders response_headers; | |
421 SpdyBalsaUtils::SpdyHeadersToResponseHeaders( | |
422 client_stream->response_headers(), &response_headers); | |
423 | 412 |
| 413 const SpdyHeaderBlock& response_headers = client_stream->response_headers(); |
424 if (response_listener_.get() != nullptr) { | 414 if (response_listener_.get() != nullptr) { |
425 response_listener_->OnCompleteResponse(stream->id(), response_headers, | 415 response_listener_->OnCompleteResponse(stream->id(), response_headers, |
426 client_stream->data()); | 416 client_stream->data()); |
427 } | 417 } |
428 | 418 |
429 // Store response headers and body. | 419 // Store response headers and body. |
430 if (store_response_) { | 420 if (store_response_) { |
431 latest_response_code_ = response_headers.parsed_response_code(); | 421 auto status = response_headers.find(":status"); |
432 response_headers.DumpHeadersToString(&latest_response_headers_); | 422 if (status == response_headers.end() || |
| 423 !StringToInt(status->second, &latest_response_code_)) { |
| 424 LOG(ERROR) << "Invalid response headers: no status code"; |
| 425 } |
| 426 latest_response_headers_ = response_headers.DebugString(); |
| 427 latest_response_header_block_ = response_headers.Clone(); |
433 latest_response_body_ = client_stream->data(); | 428 latest_response_body_ = client_stream->data(); |
434 latest_response_trailers_ = | 429 latest_response_trailers_ = |
435 client_stream->received_trailers().DebugString(); | 430 client_stream->received_trailers().DebugString(); |
436 } | 431 } |
437 } | 432 } |
438 | 433 |
439 bool QuicClient::CheckVary(const SpdyHeaderBlock& client_request, | 434 bool QuicClient::CheckVary(const SpdyHeaderBlock& client_request, |
440 const SpdyHeaderBlock& promise_request, | 435 const SpdyHeaderBlock& promise_request, |
441 const SpdyHeaderBlock& promise_response) { | 436 const SpdyHeaderBlock& promise_response) { |
442 return true; | 437 return true; |
(...skipping 13 matching lines...) Expand all Loading... |
456 size_t QuicClient::latest_response_code() const { | 451 size_t QuicClient::latest_response_code() const { |
457 QUIC_BUG_IF(!store_response_) << "Response not stored!"; | 452 QUIC_BUG_IF(!store_response_) << "Response not stored!"; |
458 return latest_response_code_; | 453 return latest_response_code_; |
459 } | 454 } |
460 | 455 |
461 const string& QuicClient::latest_response_headers() const { | 456 const string& QuicClient::latest_response_headers() const { |
462 QUIC_BUG_IF(!store_response_) << "Response not stored!"; | 457 QUIC_BUG_IF(!store_response_) << "Response not stored!"; |
463 return latest_response_headers_; | 458 return latest_response_headers_; |
464 } | 459 } |
465 | 460 |
| 461 const SpdyHeaderBlock& QuicClient::latest_response_header_block() const { |
| 462 QUIC_BUG_IF(!store_response_) << "Response not stored!"; |
| 463 return latest_response_header_block_; |
| 464 } |
| 465 |
466 const string& QuicClient::latest_response_body() const { | 466 const string& QuicClient::latest_response_body() const { |
467 QUIC_BUG_IF(!store_response_) << "Response not stored!"; | 467 QUIC_BUG_IF(!store_response_) << "Response not stored!"; |
468 return latest_response_body_; | 468 return latest_response_body_; |
469 } | 469 } |
470 | 470 |
471 const string& QuicClient::latest_response_trailers() const { | 471 const string& QuicClient::latest_response_trailers() const { |
472 QUIC_BUG_IF(!store_response_) << "Response not stored!"; | 472 QUIC_BUG_IF(!store_response_) << "Response not stored!"; |
473 return latest_response_trailers_; | 473 return latest_response_trailers_; |
474 } | 474 } |
475 | 475 |
(...skipping 17 matching lines...) Expand all Loading... |
493 return fd_address_map_.back().first; | 493 return fd_address_map_.back().first; |
494 } | 494 } |
495 | 495 |
496 void QuicClient::ProcessPacket(const IPEndPoint& self_address, | 496 void QuicClient::ProcessPacket(const IPEndPoint& self_address, |
497 const IPEndPoint& peer_address, | 497 const IPEndPoint& peer_address, |
498 const QuicReceivedPacket& packet) { | 498 const QuicReceivedPacket& packet) { |
499 session()->connection()->ProcessUdpPacket(self_address, peer_address, packet); | 499 session()->connection()->ProcessUdpPacket(self_address, peer_address, packet); |
500 } | 500 } |
501 | 501 |
502 } // namespace net | 502 } // namespace net |
OLD | NEW |