| 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 |