diff --git a/src/net/spdy/spdy_proxy_client_socket.cc b/src/net/spdy/spdy_proxy_client_socket.cc index 6fd314fa80..64c7803c9e 100644 --- a/src/net/spdy/spdy_proxy_client_socket.cc +++ b/src/net/spdy/spdy_proxy_client_socket.cc @@ -50,6 +50,8 @@ SpdyProxyClientSocket::SpdyProxyClientSocket( user_buffer_len_(0), write_buffer_len_(0), was_ever_used_(false), + use_fastopen_(false), + read_headers_pending_(false), net_log_(NetLogWithSource::Make(spdy_stream->net_log().net_log(), NetLogSourceType::PROXY_CLIENT_SOCKET)), source_dependency_(source_net_log.source()) { @@ -332,6 +334,20 @@ int SpdyProxyClientSocket::DoLoop(int last_io_result) { rv = DoReadReplyComplete(rv); net_log_.EndEventWithNetErrorCode( NetLogEventType::HTTP_TRANSACTION_TUNNEL_READ_HEADERS, rv); + if (use_fastopen_ && read_headers_pending_) { + read_headers_pending_ = false; + if (rv < 0) { + // read_callback_ cannot be called. + if (!read_callback_) + rv = ERR_IO_PENDING; + // read_callback_ will be called with this error and be reset. + // Further data after that will be ignored. + next_state_ = STATE_DISCONNECTED; + } else { + // Does not call read_callback_ from here if headers are OK. + rv = ERR_IO_PENDING; + } + } break; default: NOTREACHED() << "bad state"; @@ -372,6 +388,10 @@ int SpdyProxyClientSocket::DoSendRequest() { HttpRequestHeaders proxy_delegate_headers; proxy_delegate_->OnBeforeTunnelRequest(proxy_server_, &proxy_delegate_headers); + if (proxy_delegate_headers.HasHeader("fastopen")) { + proxy_delegate_headers.RemoveHeader("fastopen"); + use_fastopen_ = true; + } request_.extra_headers.MergeFrom(proxy_delegate_headers); } @@ -394,6 +414,12 @@ int SpdyProxyClientSocket::DoSendRequestComplete(int result) { if (result < 0) return result; + if (use_fastopen_) { + read_headers_pending_ = true; + next_state_ = STATE_OPEN; + return OK; + } + // Wait for HEADERS frame from the server next_state_ = STATE_READ_REPLY_COMPLETE; return ERR_IO_PENDING; @@ -455,6 +481,10 @@ void SpdyProxyClientSocket::OnEarlyHintsReceived( void SpdyProxyClientSocket::OnHeadersReceived( const spdy::Http2HeaderBlock& response_headers, const spdy::Http2HeaderBlock* pushed_request_headers) { + if (use_fastopen_ && read_headers_pending_ && next_state_ == STATE_OPEN) { + next_state_ = STATE_READ_REPLY_COMPLETE; + } + // If we've already received the reply, existing headers are too late. // TODO(mbelshe): figure out a way to make HEADERS frames useful after the // initial response. diff --git a/src/net/spdy/spdy_proxy_client_socket.h b/src/net/spdy/spdy_proxy_client_socket.h index 096b3845dd..1d29ea1fd0 100644 --- a/src/net/spdy/spdy_proxy_client_socket.h +++ b/src/net/spdy/spdy_proxy_client_socket.h @@ -183,6 +183,9 @@ class NET_EXPORT_PRIVATE SpdyProxyClientSocket : public ProxyClientSocket, // True if the transport socket has ever sent data. bool was_ever_used_; + bool use_fastopen_; + bool read_headers_pending_; + const NetLogWithSource net_log_; const NetLogSource source_dependency_;