Index: net/quic/chromium/quic_chromium_client_stream.cc |
diff --git a/net/quic/chromium/quic_chromium_client_stream.cc b/net/quic/chromium/quic_chromium_client_stream.cc |
index 5eb505a382db4011e8ab0e6ed3bd9f794c365855..ad706a56e1bc34b45fc0729cf17df94c09a6339d 100644 |
--- a/net/quic/chromium/quic_chromium_client_stream.cc |
+++ b/net/quic/chromium/quic_chromium_client_stream.cc |
@@ -23,7 +23,7 @@ namespace net { |
QuicChromiumClientStream::Handle::Handle(QuicChromiumClientStream* stream, |
Delegate* delegate) |
- : stream_(stream), delegate_(delegate) { |
+ : stream_(stream), delegate_(delegate), read_headers_buffer_(nullptr) { |
SaveState(); |
} |
@@ -40,10 +40,15 @@ void QuicChromiumClientStream::Handle::ClearDelegate() { |
delegate_ = nullptr; |
} |
-void QuicChromiumClientStream::Handle::OnInitialHeadersAvailable( |
- const SpdyHeaderBlock& headers, |
- size_t frame_len) { |
- delegate_->OnInitialHeadersAvailable(headers, frame_len); |
+void QuicChromiumClientStream::Handle::OnInitialHeadersAvailable() { |
+ if (!read_headers_callback_) |
+ return; // Wait for ReadInitialHeaders to be called. |
+ |
+ int rv = ERR_QUIC_PROTOCOL_ERROR; |
+ if (!stream_->DeliverInitialHeaders(read_headers_buffer_, &rv)) |
+ rv = ERR_QUIC_PROTOCOL_ERROR; |
+ |
+ ResetAndReturn(&read_headers_callback_).Run(rv); |
} |
void QuicChromiumClientStream::Handle::OnTrailingHeadersAvailable( |
@@ -78,6 +83,21 @@ void QuicChromiumClientStream::Handle::OnError(int error) { |
} |
} |
+int QuicChromiumClientStream::Handle::ReadInitialHeaders( |
+ SpdyHeaderBlock* header_block, |
+ const CompletionCallback& callback) { |
+ if (!stream_) |
+ return ERR_CONNECTION_CLOSED; |
+ |
+ int frame_len = 0; |
+ if (stream_->DeliverInitialHeaders(header_block, &frame_len)) |
+ return frame_len; |
+ |
+ read_headers_buffer_ = header_block; |
+ read_headers_callback_ = callback; |
+ return ERR_IO_PENDING; |
+} |
+ |
size_t QuicChromiumClientStream::Handle::WriteHeaders( |
SpdyHeaderBlock header_block, |
bool fin, |
@@ -271,16 +291,14 @@ void QuicChromiumClientStream::OnInitialHeadersComplete( |
ConsumeHeaderList(); |
session_->OnInitialHeadersComplete(id(), header_block); |
- if (handle_) { |
- // The handle will receive the headers via a posted task. |
- NotifyHandleOfInitialHeadersAvailableLater(std::move(header_block), |
- frame_len); |
- return; |
- } |
- |
// Buffer the headers and deliver them when the handle arrives. |
initial_headers_ = std::move(header_block); |
initial_headers_frame_len_ = frame_len; |
+ |
+ if (handle_) { |
+ // The handle will be notified of the headers via a posted task. |
+ NotifyHandleOfInitialHeadersAvailableLater(); |
+ } |
} |
void QuicChromiumClientStream::OnTrailingHeadersComplete( |
@@ -414,10 +432,8 @@ QuicChromiumClientStream::CreateHandle( |
handle_ = handle.get(); |
// Should this perhaps be via PostTask to make reasoning simpler? |
- if (!initial_headers_.empty()) { |
- handle_->OnInitialHeadersAvailable(std::move(initial_headers_), |
- initial_headers_frame_len_); |
- } |
+ if (!initial_headers_.empty()) |
+ handle_->OnInitialHeadersAvailable(); |
return handle; |
} |
@@ -450,31 +466,21 @@ int QuicChromiumClientStream::Read(IOBuffer* buf, int buf_len) { |
return bytes_read; |
} |
-void QuicChromiumClientStream::NotifyHandleOfInitialHeadersAvailableLater( |
- SpdyHeaderBlock headers, |
- size_t frame_len) { |
+void QuicChromiumClientStream::NotifyHandleOfInitialHeadersAvailableLater() { |
DCHECK(handle_); |
base::ThreadTaskRunnerHandle::Get()->PostTask( |
FROM_HERE, |
base::Bind( |
&QuicChromiumClientStream::NotifyHandleOfInitialHeadersAvailable, |
- weak_factory_.GetWeakPtr(), base::Passed(std::move(headers)), |
- frame_len)); |
+ weak_factory_.GetWeakPtr())); |
} |
-void QuicChromiumClientStream::NotifyHandleOfInitialHeadersAvailable( |
- SpdyHeaderBlock headers, |
- size_t frame_len) { |
+void QuicChromiumClientStream::NotifyHandleOfInitialHeadersAvailable() { |
if (!handle_) |
return; |
- DCHECK(!headers_delivered_); |
- headers_delivered_ = true; |
- net_log_.AddEvent( |
- NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_READ_RESPONSE_HEADERS, |
- base::Bind(&SpdyHeaderBlockNetLogCallback, &headers)); |
- |
- handle_->OnInitialHeadersAvailable(headers, frame_len); |
+ if (!headers_delivered_) |
+ handle_->OnInitialHeadersAvailable(); |
} |
void QuicChromiumClientStream::NotifyHandleOfTrailingHeadersAvailableLater( |
@@ -503,10 +509,24 @@ void QuicChromiumClientStream::NotifyHandleOfTrailingHeadersAvailable( |
net_log_.AddEvent( |
NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_READ_RESPONSE_TRAILERS, |
base::Bind(&SpdyHeaderBlockNetLogCallback, &headers)); |
- |
handle_->OnTrailingHeadersAvailable(headers, frame_len); |
} |
+bool QuicChromiumClientStream::DeliverInitialHeaders(SpdyHeaderBlock* headers, |
+ int* frame_len) { |
+ if (initial_headers_.empty()) |
+ return false; |
+ |
+ headers_delivered_ = true; |
+ net_log_.AddEvent( |
+ NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_READ_RESPONSE_HEADERS, |
+ base::Bind(&SpdyHeaderBlockNetLogCallback, &initial_headers_)); |
+ |
+ *headers = std::move(initial_headers_); |
+ *frame_len = initial_headers_frame_len_; |
+ return true; |
+} |
+ |
void QuicChromiumClientStream::NotifyHandleOfDataAvailableLater() { |
DCHECK(handle_); |
base::ThreadTaskRunnerHandle::Get()->PostTask( |