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/quic/quic_http_stream.h" | 5 #include "net/quic/quic_http_stream.h" |
6 | 6 |
7 #include "base/callback_helpers.h" | 7 #include "base/callback_helpers.h" |
8 #include "base/stringprintf.h" | 8 #include "base/stringprintf.h" |
9 #include "net/base/io_buffer.h" | 9 #include "net/base/io_buffer.h" |
10 #include "net/base/net_errors.h" | 10 #include "net/base/net_errors.h" |
11 #include "net/http/http_response_headers.h" | 11 #include "net/http/http_response_headers.h" |
12 #include "net/http/http_util.h" | 12 #include "net/http/http_util.h" |
13 #include "net/quic/quic_client_session.h" | 13 #include "net/quic/quic_client_session.h" |
14 #include "net/quic/quic_reliable_client_stream.h" | 14 #include "net/quic/quic_reliable_client_stream.h" |
15 #include "net/quic/quic_utils.h" | 15 #include "net/quic/quic_utils.h" |
16 #include "net/socket/next_proto.h" | 16 #include "net/socket/next_proto.h" |
17 #include "net/spdy/spdy_frame_builder.h" | 17 #include "net/spdy/spdy_frame_builder.h" |
18 #include "net/spdy/spdy_framer.h" | 18 #include "net/spdy/spdy_framer.h" |
19 #include "net/spdy/spdy_http_utils.h" | 19 #include "net/spdy/spdy_http_utils.h" |
20 | 20 |
21 namespace net { | 21 namespace net { |
22 | 22 |
23 static const size_t kHeaderBufInitialSize = 4096; | 23 static const size_t kHeaderBufInitialSize = 4096; |
24 | 24 |
25 QuicHttpStream::QuicHttpStream(QuicReliableClientStream* stream, | 25 QuicHttpStream::QuicHttpStream(QuicReliableClientStream* stream) |
26 bool use_spdy) | |
27 : io_state_(STATE_NONE), | 26 : io_state_(STATE_NONE), |
28 stream_(stream), | 27 stream_(stream), |
29 request_info_(NULL), | 28 request_info_(NULL), |
30 request_body_stream_(NULL), | 29 request_body_stream_(NULL), |
31 response_info_(NULL), | 30 response_info_(NULL), |
32 response_status_(OK), | 31 response_status_(OK), |
33 response_headers_received_(false), | 32 response_headers_received_(false), |
34 use_spdy_(use_spdy), | |
35 read_buf_(new GrowableIOBuffer()), | 33 read_buf_(new GrowableIOBuffer()), |
36 user_buffer_len_(0), | 34 user_buffer_len_(0), |
37 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { | 35 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { |
38 DCHECK(stream_); | 36 DCHECK(stream_); |
39 stream_->SetDelegate(this); | 37 stream_->SetDelegate(this); |
40 } | 38 } |
41 | 39 |
42 QuicHttpStream::~QuicHttpStream() { | 40 QuicHttpStream::~QuicHttpStream() { |
43 Close(false); | 41 Close(false); |
44 } | 42 } |
(...skipping 12 matching lines...) Expand all Loading... |
57 int QuicHttpStream::SendRequest(const HttpRequestHeaders& request_headers, | 55 int QuicHttpStream::SendRequest(const HttpRequestHeaders& request_headers, |
58 HttpResponseInfo* response, | 56 HttpResponseInfo* response, |
59 const CompletionCallback& callback) { | 57 const CompletionCallback& callback) { |
60 CHECK(stream_); | 58 CHECK(stream_); |
61 CHECK(!request_body_stream_); | 59 CHECK(!request_body_stream_); |
62 CHECK(!response_info_); | 60 CHECK(!response_info_); |
63 CHECK(!callback.is_null()); | 61 CHECK(!callback.is_null()); |
64 CHECK(response); | 62 CHECK(response); |
65 | 63 |
66 // Store the serialized request headers. | 64 // Store the serialized request headers. |
67 if (use_spdy_) { | 65 SpdyHeaderBlock headers; |
68 SpdyHeaderBlock headers; | 66 CreateSpdyHeadersFromHttpRequest(*request_info_, request_headers, |
69 CreateSpdyHeadersFromHttpRequest(*request_info_, request_headers, | 67 &headers, 3, /*direct=*/true); |
70 &headers, 3, /*direct=*/true); | 68 size_t len = SpdyFramer::GetSerializedLength(3, &headers); |
71 size_t len = SpdyFramer::GetSerializedLength(3, &headers); | 69 SpdyFrameBuilder builder(len); |
72 SpdyFrameBuilder builder(len); | 70 SpdyFramer::WriteHeaderBlock(&builder, 3, &headers); |
73 SpdyFramer::WriteHeaderBlock(&builder, 3, &headers); | 71 scoped_ptr<SpdyFrame> frame(builder.take()); |
74 scoped_ptr<SpdyFrame> frame(builder.take()); | 72 request_ = std::string(frame->data(), len); |
75 request_ = std::string(frame->data(), len); | 73 // Log the actual request with the URL Request's net log. |
76 // Log the actual request with the URL Request's net log. | 74 stream_net_log_.AddEvent( |
77 stream_net_log_.AddEvent( | 75 NetLog::TYPE_HTTP_TRANSACTION_SPDY_SEND_REQUEST_HEADERS, |
78 NetLog::TYPE_HTTP_TRANSACTION_SPDY_SEND_REQUEST_HEADERS, | 76 base::Bind(&SpdyHeaderBlockNetLogCallback, &headers)); |
79 base::Bind(&SpdyHeaderBlockNetLogCallback, &headers)); | 77 // Also log to the QuicSession's net log. |
80 // Also log to the QuicSession's net log. | 78 stream_->net_log().AddEvent( |
81 stream_->net_log().AddEvent( | 79 NetLog::TYPE_QUIC_HTTP_STREAM_SEND_REQUEST_HEADERS, |
82 NetLog::TYPE_QUIC_HTTP_STREAM_SEND_REQUEST_HEADERS, | 80 base::Bind(&SpdyHeaderBlockNetLogCallback, &headers)); |
83 base::Bind(&SpdyHeaderBlockNetLogCallback, &headers)); | |
84 } else { | |
85 std::string path = HttpUtil::PathForRequest(request_info_->url); | |
86 std::string first_line = base::StringPrintf("%s %s HTTP/1.1\r\n", | |
87 request_info_->method.c_str(), | |
88 path.c_str()); | |
89 request_ = first_line + request_headers.ToString(); | |
90 // Log the actual request with the URL Request's net log. | |
91 stream_net_log_.AddEvent( | |
92 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS, | |
93 base::Bind(&HttpRequestHeaders::NetLogCallback, | |
94 base::Unretained(&request_headers), | |
95 &first_line)); | |
96 // Also log to the QuicSession's net log. | |
97 stream_->net_log().AddEvent( | |
98 NetLog::TYPE_QUIC_HTTP_STREAM_SEND_REQUEST_HEADERS, | |
99 base::Bind(&HttpRequestHeaders::NetLogCallback, | |
100 base::Unretained(&request_headers), | |
101 &first_line)); | |
102 } | |
103 | 81 |
104 // Store the request body. | 82 // Store the request body. |
105 request_body_stream_ = request_info_->upload_data_stream; | 83 request_body_stream_ = request_info_->upload_data_stream; |
106 if (request_body_stream_ && (request_body_stream_->size() || | 84 if (request_body_stream_ && (request_body_stream_->size() || |
107 request_body_stream_->is_chunked())) { | 85 request_body_stream_->is_chunked())) { |
108 // Use kMaxPacketSize as the buffer size, since the request | 86 // Use kMaxPacketSize as the buffer size, since the request |
109 // body data is written with this size at a time. | 87 // body data is written with this size at a time. |
110 // TODO(rch): use a smarter value since we can't write an entire | 88 // TODO(rch): use a smarter value since we can't write an entire |
111 // packet due to overhead. | 89 // packet due to overhead. |
112 raw_request_body_buf_ = new IOBufferWithSize(kMaxPacketSize); | 90 raw_request_body_buf_ = new IOBufferWithSize(kMaxPacketSize); |
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
455 if (rv < 0) { | 433 if (rv < 0) { |
456 io_state_ = STATE_NONE; | 434 io_state_ = STATE_NONE; |
457 return rv; | 435 return rv; |
458 } | 436 } |
459 | 437 |
460 io_state_ = STATE_READ_REQUEST_BODY; | 438 io_state_ = STATE_READ_REQUEST_BODY; |
461 return OK; | 439 return OK; |
462 } | 440 } |
463 | 441 |
464 int QuicHttpStream::ParseResponseHeaders() { | 442 int QuicHttpStream::ParseResponseHeaders() { |
465 if (use_spdy_) { | 443 size_t read_buf_len = static_cast<size_t>(read_buf_->offset()); |
466 size_t read_buf_len = static_cast<size_t>(read_buf_->offset()); | 444 SpdyFramer framer(3); |
467 SpdyFramer framer(3); | 445 SpdyHeaderBlock headers; |
468 SpdyHeaderBlock headers; | 446 char* data = read_buf_->StartOfBuffer(); |
469 char* data = read_buf_->StartOfBuffer(); | 447 size_t len = framer.ParseHeaderBlockInBuffer(data, read_buf_->offset(), |
470 size_t len = framer.ParseHeaderBlockInBuffer(data, read_buf_->offset(), | 448 &headers); |
471 &headers); | |
472 | 449 |
473 if (len == 0) { | 450 if (len == 0) { |
474 return ERR_IO_PENDING; | |
475 } | |
476 | |
477 // Save the remaining received data. | |
478 size_t delta = read_buf_len - len; | |
479 if (delta > 0) { | |
480 BufferResponseBody(data + len, delta); | |
481 } | |
482 | |
483 // The URLRequest logs these headers, so only log to the QuicSession's | |
484 // net log. | |
485 stream_->net_log().AddEvent( | |
486 NetLog::TYPE_QUIC_HTTP_STREAM_READ_RESPONSE_HEADERS, | |
487 base::Bind(&SpdyHeaderBlockNetLogCallback, &headers)); | |
488 | |
489 if (!SpdyHeadersToHttpResponse(headers, 3, response_info_)) { | |
490 DLOG(WARNING) << "Invalid headers"; | |
491 return ERR_QUIC_PROTOCOL_ERROR; | |
492 } | |
493 // Put the peer's IP address and port into the response. | |
494 IPEndPoint address = stream_->GetPeerAddress(); | |
495 response_info_->socket_address = HostPortPair::FromIPEndPoint(address); | |
496 response_info_->vary_data.Init(*request_info_, *response_info_->headers); | |
497 response_headers_received_ = true; | |
498 | |
499 return OK; | |
500 } | |
501 int end_offset = HttpUtil::LocateEndOfHeaders(read_buf_->StartOfBuffer(), | |
502 read_buf_->offset(), 0); | |
503 | |
504 if (end_offset == -1) { | |
505 return ERR_IO_PENDING; | 451 return ERR_IO_PENDING; |
506 } | 452 } |
507 | 453 |
508 if (!stream_) | 454 // Save the remaining received data. |
509 return ERR_UNEXPECTED; | 455 size_t delta = read_buf_len - len; |
510 | 456 if (delta > 0) { |
511 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders( | 457 BufferResponseBody(data + len, delta); |
512 HttpUtil::AssembleRawHeaders(read_buf_->StartOfBuffer(), end_offset)); | 458 } |
513 | |
514 // Put the peer's IP address and port into the response. | |
515 IPEndPoint address = stream_->GetPeerAddress(); | |
516 response_info_->socket_address = HostPortPair::FromIPEndPoint(address); | |
517 response_info_->headers = headers; | |
518 response_info_->vary_data.Init(*request_info_, *response_info_->headers); | |
519 response_headers_received_ = true; | |
520 | 459 |
521 // The URLRequest logs these headers, so only log to the QuicSession's | 460 // The URLRequest logs these headers, so only log to the QuicSession's |
522 // net log. | 461 // net log. |
523 stream_->net_log().AddEvent( | 462 stream_->net_log().AddEvent( |
524 NetLog::TYPE_QUIC_HTTP_STREAM_READ_RESPONSE_HEADERS, | 463 NetLog::TYPE_QUIC_HTTP_STREAM_READ_RESPONSE_HEADERS, |
525 base::Bind(&HttpResponseHeaders::NetLogCallback, | 464 base::Bind(&SpdyHeaderBlockNetLogCallback, &headers)); |
526 response_info_->headers)); | |
527 | 465 |
528 // Save the remaining received data. | 466 if (!SpdyHeadersToHttpResponse(headers, 3, response_info_)) { |
529 int delta = read_buf_->offset() - end_offset; | 467 DLOG(WARNING) << "Invalid headers"; |
530 if (delta > 0) { | 468 return ERR_QUIC_PROTOCOL_ERROR; |
531 BufferResponseBody(read_buf_->data(), delta); | |
532 } | 469 } |
| 470 // Put the peer's IP address and port into the response. |
| 471 IPEndPoint address = stream_->GetPeerAddress(); |
| 472 response_info_->socket_address = HostPortPair::FromIPEndPoint(address); |
| 473 response_info_->vary_data.Init(*request_info_, *response_info_->headers); |
| 474 response_headers_received_ = true; |
533 | 475 |
534 return OK; | 476 return OK; |
535 } | 477 } |
536 | 478 |
537 void QuicHttpStream::BufferResponseBody(const char* data, int length) { | 479 void QuicHttpStream::BufferResponseBody(const char* data, int length) { |
538 if (length == 0) | 480 if (length == 0) |
539 return; | 481 return; |
540 IOBufferWithSize* io_buffer = new IOBufferWithSize(length); | 482 IOBufferWithSize* io_buffer = new IOBufferWithSize(length); |
541 memcpy(io_buffer->data(), data, length); | 483 memcpy(io_buffer->data(), data, length); |
542 response_body_.push_back(make_scoped_refptr(io_buffer)); | 484 response_body_.push_back(make_scoped_refptr(io_buffer)); |
543 } | 485 } |
544 | 486 |
545 } // namespace net | 487 } // namespace net |
OLD | NEW |