diff options
author | rch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-28 04:58:38 +0000 |
---|---|---|
committer | rch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-28 04:58:38 +0000 |
commit | 1c703210a2dbf7d5ff0ba06029e0411f0728c4e1 (patch) | |
tree | c6584610de9c306b6345f2395fdcd00bbf250c48 | |
parent | 06fb18592e5fad681cf33d80bae8a51862d8a923 (diff) | |
download | chromium_src-1c703210a2dbf7d5ff0ba06029e0411f0728c4e1.zip chromium_src-1c703210a2dbf7d5ff0ba06029e0411f0728c4e1.tar.gz chromium_src-1c703210a2dbf7d5ff0ba06029e0411f0728c4e1.tar.bz2 |
Revert 60747 - Add a new class SpdyProxyClientSocket which implements ClientSocket
by sending a CONNECT request via a SPDY SYN_STREAM frame to a SPDY proxy,
and then reading/writing data to/from SPDY Data frames.
BUG=29625
TEST=none
Review URL: http://codereview.chromium.org/3432009
TBR=rch@chromium.org
Review URL: http://codereview.chromium.org/3391029
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@60754 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | net/http/http_proxy_client_socket.cc | 33 | ||||
-rw-r--r-- | net/http/http_proxy_utils.cc | 39 | ||||
-rw-r--r-- | net/http/http_proxy_utils.h | 28 | ||||
-rw-r--r-- | net/net.gyp | 5 | ||||
-rw-r--r-- | net/spdy/spdy_framer.h | 10 | ||||
-rw-r--r-- | net/spdy/spdy_http_utils.cc | 2 | ||||
-rw-r--r-- | net/spdy/spdy_proxy_client_socket.cc | 437 | ||||
-rw-r--r-- | net/spdy/spdy_proxy_client_socket.h | 183 | ||||
-rw-r--r-- | net/spdy/spdy_proxy_client_socket_unittest.cc | 894 | ||||
-rw-r--r-- | net/spdy/spdy_session.h | 10 | ||||
-rw-r--r-- | net/spdy/spdy_stream.cc | 7 | ||||
-rw-r--r-- | net/spdy/spdy_stream.h | 7 |
12 files changed, 35 insertions, 1620 deletions
diff --git a/net/http/http_proxy_client_socket.cc b/net/http/http_proxy_client_socket.cc index ddefe8e..ccc5d5d 100644 --- a/net/http/http_proxy_client_socket.cc +++ b/net/http/http_proxy_client_socket.cc @@ -14,13 +14,42 @@ #include "net/base/net_util.h" #include "net/http/http_net_log_params.h" #include "net/http/http_network_session.h" -#include "net/http/http_proxy_utils.h" #include "net/http/http_request_info.h" #include "net/http/http_stream_parser.h" #include "net/socket/client_socket_handle.h" namespace net { +namespace { + +// The HTTP CONNECT method for establishing a tunnel connection is documented +// in draft-luotonen-web-proxy-tunneling-01.txt and RFC 2817, Sections 5.2 and +// 5.3. +void BuildTunnelRequest(const HttpRequestInfo* request_info, + const HttpRequestHeaders& authorization_headers, + const HostPortPair& endpoint, + std::string* request_line, + HttpRequestHeaders* request_headers) { + // RFC 2616 Section 9 says the Host request-header field MUST accompany all + // HTTP/1.1 requests. Add "Proxy-Connection: keep-alive" for compat with + // HTTP/1.0 proxies such as Squid (required for NTLM authentication). + *request_line = base::StringPrintf( + "CONNECT %s HTTP/1.1\r\n", endpoint.ToString().c_str()); + request_headers->SetHeader(HttpRequestHeaders::kHost, + GetHostAndOptionalPort(request_info->url)); + request_headers->SetHeader(HttpRequestHeaders::kProxyConnection, + "keep-alive"); + + std::string user_agent; + if (request_info->extra_headers.GetHeader(HttpRequestHeaders::kUserAgent, + &user_agent)) + request_headers->SetHeader(HttpRequestHeaders::kUserAgent, user_agent); + + request_headers->MergeFrom(authorization_headers); +} + +} // namespace + HttpProxyClientSocket::HttpProxyClientSocket( ClientSocketHandle* transport_socket, const GURL& request_url, @@ -329,7 +358,7 @@ int HttpProxyClientSocket::DoSendRequest() { auth_->AddAuthorizationHeader(&authorization_headers); std::string request_line; HttpRequestHeaders request_headers; - BuildTunnelRequest(request_, authorization_headers, endpoint_, + BuildTunnelRequest(&request_, authorization_headers, endpoint_, &request_line, &request_headers); if (net_log_.IsLoggingAll()) { net_log_.AddEvent( diff --git a/net/http/http_proxy_utils.cc b/net/http/http_proxy_utils.cc deleted file mode 100644 index 3e4fb8b..0000000 --- a/net/http/http_proxy_utils.cc +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/http/http_proxy_utils.h" - -#include "base/string_util.h" -#include "googleurl/src/gurl.h" -#include "net/base/host_port_pair.h" -#include "net/base/net_util.h" -#include "net/http/http_request_info.h" - -namespace net { - -void BuildTunnelRequest( - const HttpRequestInfo& request_info, - const HttpRequestHeaders& auth_headers, - const HostPortPair& endpoint, - std::string* request_line, - HttpRequestHeaders* request_headers) { - // RFC 2616 Section 9 says the Host request-header field MUST accompany all - // HTTP/1.1 requests. Add "Proxy-Connection: keep-alive" for compat with - // HTTP/1.0 proxies such as Squid (required for NTLM authentication). - *request_line = StringPrintf( - "CONNECT %s HTTP/1.1\r\n", endpoint.ToString().c_str()); - request_headers->SetHeader(HttpRequestHeaders::kHost, - GetHostAndOptionalPort(request_info.url)); - request_headers->SetHeader(HttpRequestHeaders::kProxyConnection, - "keep-alive"); - - std::string user_agent; - if (request_info.extra_headers.GetHeader(HttpRequestHeaders::kUserAgent, - &user_agent)) - request_headers->SetHeader(HttpRequestHeaders::kUserAgent, user_agent); - - request_headers->MergeFrom(auth_headers); -} - -} // namespace net diff --git a/net/http/http_proxy_utils.h b/net/http/http_proxy_utils.h deleted file mode 100644 index 9d18fc8..0000000 --- a/net/http/http_proxy_utils.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_HTTP_HTTP_PROXY_UTILS_H_ -#define NET_HTTP_HTTP_PROXY_UTILS_H_ -#pragma once - -#include <string> - -namespace net { - -struct HttpRequestInfo; -class HttpRequestHeaders; -class HostPortPair; - -// The HTTP CONNECT method for establishing a tunnel connection is documented -// in draft-luotonen-web-proxy-tunneling-01.txt and RFC 2817, Sections 5.2 and -// 5.3. -void BuildTunnelRequest(const HttpRequestInfo& request_info, - const HttpRequestHeaders& auth_headers, - const HostPortPair& endpoint, - std::string* request_line, - HttpRequestHeaders* request_headers); - -} // namespace net - -#endif // NET_HTTP_HTTP_PROXY_UTILS_H_ diff --git a/net/net.gyp b/net/net.gyp index b93ce86..06105fa 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -453,8 +453,6 @@ 'http/http_proxy_client_socket.h', 'http/http_proxy_client_socket_pool.cc', 'http/http_proxy_client_socket_pool.h', - 'http/http_proxy_utils.cc', - 'http/http_proxy_utils.h', 'http/http_util.cc', 'http/http_util_icu.cc', 'http/http_util.h', @@ -572,8 +570,6 @@ 'spdy/spdy_io_buffer.cc', 'spdy/spdy_io_buffer.h', 'spdy/spdy_protocol.h', - 'spdy/spdy_proxy_client_socket.cc', - 'spdy/spdy_proxy_client_socket.h', 'spdy/spdy_session.cc', 'spdy/spdy_session.h', 'spdy/spdy_session_pool.cc', @@ -849,7 +845,6 @@ 'spdy/spdy_http_stream_unittest.cc', 'spdy/spdy_network_transaction_unittest.cc', 'spdy/spdy_protocol_test.cc', - 'spdy/spdy_proxy_client_socket_unittest.cc', 'spdy/spdy_session_unittest.cc', 'spdy/spdy_stream_unittest.cc', 'spdy/spdy_test_util.cc', diff --git a/net/spdy/spdy_framer.h b/net/spdy/spdy_framer.h index 00ddac0..e6d0e15 100644 --- a/net/spdy/spdy_framer.h +++ b/net/spdy/spdy_framer.h @@ -26,11 +26,10 @@ typedef struct z_stream_s z_stream; // Forward declaration for zlib. namespace net { class HttpNetworkLayer; class HttpNetworkTransactionTest; -class SpdyHttpStreamTest; class SpdyNetworkTransactionTest; -class SpdyProxyClientSocketTest; class SpdySessionTest; class SpdyStreamTest; +class SpdyHttpStreamTest; } namespace spdy { @@ -249,12 +248,11 @@ class SpdyFramer { protected: FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, DataCompression); FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, UnclosedStreamDataCompressors); - friend class net::HttpNetworkLayer; // This is temporary for the server. - friend class net::HttpNetworkTransactionTest; - friend class net::SpdyHttpStreamTest; friend class net::SpdyNetworkTransactionTest; - friend class net::SpdyProxyClientSocketTest; + friend class net::HttpNetworkTransactionTest; + friend class net::HttpNetworkLayer; // This is temporary for the server. friend class net::SpdySessionTest; + friend class net::SpdyHttpStreamTest; friend class net::SpdyStreamTest; friend class test::TestSpdyVisitor; friend void test::FramerSetEnableCompressionHelper(SpdyFramer* framer, diff --git a/net/spdy/spdy_http_utils.cc b/net/spdy/spdy_http_utils.cc index b2ef551..d2fdd8fa 100644 --- a/net/spdy/spdy_http_utils.cc +++ b/net/spdy/spdy_http_utils.cc @@ -4,8 +4,6 @@ #include "net/spdy/spdy_http_utils.h" -#include <string> - #include "base/string_number_conversions.h" #include "base/string_util.h" #include "base/time.h" diff --git a/net/spdy/spdy_proxy_client_socket.cc b/net/spdy/spdy_proxy_client_socket.cc deleted file mode 100644 index e282d76..0000000 --- a/net/spdy/spdy_proxy_client_socket.cc +++ /dev/null @@ -1,437 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/spdy/spdy_proxy_client_socket.h" - -#include <algorithm> // min - -#include "base/logging.h" -#include "base/string_util.h" -#include "googleurl/src/gurl.h" -#include "net/base/auth.h" -#include "net/base/io_buffer.h" -#include "net/base/net_util.h" -#include "net/http/http_auth_cache.h" -#include "net/http/http_auth_handler_factory.h" -#include "net/http/http_net_log_params.h" -#include "net/http/http_proxy_utils.h" -#include "net/spdy/spdy_http_utils.h" - -namespace net { - -SpdyProxyClientSocket::SpdyProxyClientSocket( - SpdyStream* spdy_stream, - const std::string& user_agent, - const HostPortPair& endpoint, - const GURL& url, - const HostPortPair& proxy_server, - HttpAuthCache* auth_cache, - HttpAuthHandlerFactory* auth_handler_factory) - : ALLOW_THIS_IN_INITIALIZER_LIST( - io_callback_(this, &SpdyProxyClientSocket::OnIOComplete)), - next_state_(STATE_NONE), - spdy_stream_(spdy_stream), - read_callback_(NULL), - write_callback_(NULL), - endpoint_(endpoint), - auth_( - new HttpAuthController(HttpAuth::AUTH_PROXY, - GURL("http://" + proxy_server.ToString()), - auth_cache, - auth_handler_factory)), - user_buffer_(NULL), - write_buffer_len_(0), - write_bytes_outstanding_(0), - eof_has_been_read_(false), - net_log_(spdy_stream->net_log()) { - request_.method = "CONNECT"; - request_.url = url; - if (!user_agent.empty()) - request_.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, - user_agent); - spdy_stream_->SetDelegate(this); - was_ever_used_ = spdy_stream_->WasEverUsed(); -} - -SpdyProxyClientSocket::~SpdyProxyClientSocket() { - Disconnect(); -} - -// Sends a SYN_STREAM frame to the proxy with a CONNECT request -// for the specified endpoint. Waits for the server to send back -// a SYN_REPLY frame. OK will be returned if the status is 200. -// ERR_TUNNEL_CONNECTION_FAILED will be returned for any other status. -// In any of these cases, Read() may be called to retrieve the HTTP -// response body. Any other return values should be considered fatal. -// TODO(rch): handle 407 proxy auth requested correctly, perhaps -// by creating a new stream for the subsequent request. -// TODO(rch): create a more appropriate error code to disambiguate -// the HTTPS Proxy tunnel failure from an HTTP Proxy tunnel failure. -int SpdyProxyClientSocket::Connect(CompletionCallback* callback) { - DCHECK(!read_callback_); - if (next_state_ == STATE_DONE) - return OK; - - DCHECK_EQ(STATE_NONE, next_state_); - next_state_ = STATE_GENERATE_AUTH_TOKEN; - - int rv = DoLoop(OK); - if (rv == ERR_IO_PENDING) - read_callback_ = callback; - return rv; -} - -void SpdyProxyClientSocket::Disconnect() { - next_state_ = STATE_NONE; - if (spdy_stream_) - // This will cause OnClose to be invoked, which takes care of - // cleaning up all the internal state. - spdy_stream_->Cancel(); -} - -bool SpdyProxyClientSocket::IsConnected() const { - return next_state_ == STATE_DONE && spdy_stream_ != NULL && - !spdy_stream_->closed(); -} - -bool SpdyProxyClientSocket::IsConnectedAndIdle() const { - return IsConnected() && !spdy_stream_->is_idle(); -} - -void SpdyProxyClientSocket::SetSubresourceSpeculation() { - // TODO(rch): what should this implementation be? -} - -void SpdyProxyClientSocket::SetOmniboxSpeculation() { - // TODO(rch): what should this implementation be? -} - -bool SpdyProxyClientSocket::WasEverUsed() const { - return was_ever_used_ || (spdy_stream_ && spdy_stream_->WasEverUsed()); -} - -int SpdyProxyClientSocket::Read(IOBuffer* buf, int buf_len, - CompletionCallback* callback) { - DCHECK(!read_callback_); - DCHECK(!user_buffer_); - - if (!spdy_stream_) { - if (eof_has_been_read_) - return ERR_CONNECTION_CLOSED; - eof_has_been_read_ = true; - return 0; - } - - DCHECK(next_state_ == STATE_DONE); - DCHECK(buf); - user_buffer_ = new DrainableIOBuffer(buf, buf_len); - int result = PopulateUserReadBuffer(); - if (result == 0) { - DCHECK(callback); - read_callback_ = callback; - return ERR_IO_PENDING; - } - user_buffer_ = NULL; - return result; -} - -int SpdyProxyClientSocket::PopulateUserReadBuffer() { - if (!user_buffer_) - return ERR_IO_PENDING; - - while (!read_buffer_.empty() && user_buffer_->BytesRemaining() > 0) { - scoped_refptr<DrainableIOBuffer> data = read_buffer_.front(); - const int bytes_to_copy = std::min(user_buffer_->BytesRemaining(), - data->size()); - memcpy(user_buffer_->data(), data->data(), bytes_to_copy); - user_buffer_->DidConsume(bytes_to_copy); - if (bytes_to_copy == data->size()) { - // Consumed all data from this buffer - read_buffer_.pop_front(); - } else { - data->DidConsume(bytes_to_copy); - } - } - - return user_buffer_->BytesConsumed(); -} - -int SpdyProxyClientSocket::Write(IOBuffer* buf, int buf_len, - CompletionCallback* callback) { - DCHECK(!write_callback_); - if (!spdy_stream_) - return ERR_CONNECTION_CLOSED; - - write_bytes_outstanding_= buf_len; - if (buf_len <= kMaxSpdyFrameChunkSize) { - int rv = spdy_stream_->WriteStreamData(buf, buf_len, spdy::DATA_FLAG_NONE); - if (rv == ERR_IO_PENDING) { - write_callback_ = callback; - write_buffer_len_ = buf_len; - } - return rv; - } - - // Since a SPDY Data frame can only include kMaxSpdyFrameChunkSize bytes - // we need to send multiple data frames - for (int i = 0; i < buf_len; i += kMaxSpdyFrameChunkSize) { - int len = std::min(kMaxSpdyFrameChunkSize, buf_len - i); - scoped_refptr<DrainableIOBuffer> iobuf(new DrainableIOBuffer(buf, i + len)); - iobuf->SetOffset(i); - int rv = spdy_stream_->WriteStreamData(iobuf, len, spdy::DATA_FLAG_NONE); - if (rv > 0) { - write_bytes_outstanding_ -= rv; - } else if (rv != ERR_IO_PENDING) { - return rv; - } - } - if (write_bytes_outstanding_ > 0) { - write_callback_ = callback; - write_buffer_len_ = buf_len; - return ERR_IO_PENDING; - } else { - return buf_len; - } -} - -bool SpdyProxyClientSocket::SetReceiveBufferSize(int32 size) { - // Since this ClientSocket sits on top of a shared SpdySession, it - // is not safe for callers to set change this underlying socket. - return false; -} - -bool SpdyProxyClientSocket::SetSendBufferSize(int32 size) { - // Since this ClientSocket sits on top of a shared SpdySession, it - // is not safe for callers to set change this underlying socket. - return false; -} - -int SpdyProxyClientSocket::GetPeerAddress(AddressList* address) const { - if (!IsConnected()) - return ERR_UNEXPECTED; - return spdy_stream_->GetPeerAddress(address); -} - -void SpdyProxyClientSocket::OnIOComplete(int result) { - DCHECK_NE(STATE_NONE, next_state_); - int rv = DoLoop(result); - if (rv != ERR_IO_PENDING) { - CompletionCallback* c = read_callback_; - read_callback_ = NULL; - c->Run(rv); - } -} - -int SpdyProxyClientSocket::DoLoop(int last_io_result) { - DCHECK_NE(next_state_, STATE_NONE); - int rv = last_io_result; - do { - State state = next_state_; - next_state_ = STATE_NONE; - switch (state) { - case STATE_GENERATE_AUTH_TOKEN: - DCHECK_EQ(OK, rv); - rv = DoGenerateAuthToken(); - break; - case STATE_GENERATE_AUTH_TOKEN_COMPLETE: - rv = DoGenerateAuthTokenComplete(rv); - break; - case STATE_SEND_REQUEST: - DCHECK_EQ(OK, rv); - net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST, - NULL); - rv = DoSendRequest(); - break; - case STATE_SEND_REQUEST_COMPLETE: - rv = DoSendRequestComplete(rv); - net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST, - NULL); - break; - case STATE_READ_REPLY_COMPLETE: - rv = DoReadReplyComplete(rv); - net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS, - NULL); - break; - default: - NOTREACHED() << "bad state"; - rv = ERR_UNEXPECTED; - break; - } - } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE && - next_state_ != STATE_DONE); - return rv; -} - -int SpdyProxyClientSocket::DoGenerateAuthToken() { - next_state_ = STATE_GENERATE_AUTH_TOKEN_COMPLETE; - return auth_->MaybeGenerateAuthToken(&request_, &io_callback_, net_log_); -} - -int SpdyProxyClientSocket::DoGenerateAuthTokenComplete(int result) { - DCHECK_NE(ERR_IO_PENDING, result); - if (result == OK) - next_state_ = STATE_SEND_REQUEST; - return result; -} - -int SpdyProxyClientSocket::DoSendRequest() { - next_state_ = STATE_SEND_REQUEST_COMPLETE; - - // Add Proxy-Authentication header if necessary. - HttpRequestHeaders authorization_headers; - if (auth_->HaveAuth()) { - auth_->AddAuthorizationHeader(&authorization_headers); - } - - std::string request_line; - HttpRequestHeaders request_headers; - BuildTunnelRequest(request_, authorization_headers, endpoint_, &request_line, - &request_headers); - if (net_log_.IsLoggingAll()) { - net_log_.AddEvent( - NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, - new NetLogHttpRequestParameter( - request_line, request_headers)); - } - - request_.extra_headers.MergeFrom(request_headers); - linked_ptr<spdy::SpdyHeaderBlock> headers(new spdy::SpdyHeaderBlock()); - CreateSpdyHeadersFromHttpRequest(request_, headers.get(), true); - // Reset the URL to be the endpoint of the connection - (*headers)["url"] = endpoint_.ToString(); - headers->erase("scheme"); - spdy_stream_->set_spdy_headers(headers); - - return spdy_stream_->SendRequest(true); -} - -int SpdyProxyClientSocket::DoSendRequestComplete(int result) { - if (result < 0) - return result; - - // Wait for SYN_REPLY frame from the server - next_state_ = STATE_READ_REPLY_COMPLETE; - return ERR_IO_PENDING; -} - -int SpdyProxyClientSocket::DoReadReplyComplete(int result) { - // We enter this method directly from DoSendRequestComplete, since - // we are notified by a callback when the SYN_REPLY frame arrives - - if (result < 0) - return result; - - next_state_ = STATE_DONE; - // Require the "HTTP/1.x" status line for SSL CONNECT. - if (response_.headers->GetParsedHttpVersion() < HttpVersion(1, 0)) - return ERR_TUNNEL_CONNECTION_FAILED; - - if (net_log_.IsLoggingAll()) { - net_log_.AddEvent( - NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, - new NetLogHttpResponseParameter(response_.headers)); - } - - if (response_.headers->response_code() == 200) - return OK; - else - return ERR_TUNNEL_CONNECTION_FAILED; -} - -// SpdyStream::Delegate methods: -// Called when SYN frame has been sent. -// Returns true if no more data to be sent after SYN frame. -bool SpdyProxyClientSocket::OnSendHeadersComplete(int status) { - DCHECK_EQ(next_state_, STATE_SEND_REQUEST_COMPLETE); - - OnIOComplete(status); - - // We return true here so that we send |spdy_stream_| into - // STATE_OPEN (ala WebSockets). - return true; -} - -int SpdyProxyClientSocket::OnSendBody() { - // Because we use |spdy_stream_| via STATE_OPEN (ala WebSockets) - // OnSendBody() should never be called. - NOTREACHED(); - return ERR_UNEXPECTED; -} - -bool SpdyProxyClientSocket::OnSendBodyComplete(int status) { - // Because we use |spdy_stream_| via STATE_OPEN (ala WebSockets) - // OnSendBodyComplete() should never be called. - NOTREACHED(); - return false; -} - -int SpdyProxyClientSocket::OnResponseReceived( - const spdy::SpdyHeaderBlock& response, - base::Time response_time, - int status) { - // Save the response - SpdyHeadersToHttpResponse(response, &response_); - - DCHECK_EQ(next_state_, STATE_READ_REPLY_COMPLETE); - - OnIOComplete(status); - - return OK; -} - -// Called when data is received. -void SpdyProxyClientSocket::OnDataReceived(const char* data, int length) { - if (length > 0) { - // Save the received data. - scoped_refptr<IOBuffer> io_buffer = new IOBuffer(length); - memcpy(io_buffer->data(), data, length); - read_buffer_.push_back(new DrainableIOBuffer(io_buffer, length)); - } - - if (read_callback_) { - int rv = PopulateUserReadBuffer(); - CompletionCallback* c = read_callback_; - read_callback_ = NULL; - user_buffer_ = NULL; - c->Run(rv); - } -} - -void SpdyProxyClientSocket::OnDataSent(int length) { - DCHECK(write_callback_); - - write_bytes_outstanding_ -= length; - - DCHECK_GE(write_bytes_outstanding_, 0); - - if (write_bytes_outstanding_ == 0) { - int rv = write_buffer_len_; - write_buffer_len_ = 0; - write_bytes_outstanding_ = 0; - CompletionCallback* c = write_callback_; - write_callback_ = NULL; - c->Run(rv); - } -} - -void SpdyProxyClientSocket::OnClose(int status) { - DCHECK(spdy_stream_); - // If we're in the middle of connecting, we need to make sure - // we invoke the connect callback. - CompletionCallback* connect_callback = NULL; - if (next_state_ != STATE_NONE && next_state_ != STATE_DONE) { - DCHECK(read_callback_); - connect_callback = read_callback_; - } - was_ever_used_ = spdy_stream_->WasEverUsed(); - spdy_stream_ = NULL; - read_callback_ = NULL; - write_callback_ = NULL; - user_buffer_ = NULL; - read_buffer_.empty(); - if (connect_callback) - connect_callback->Run(status); -} - -} // namespace net diff --git a/net/spdy/spdy_proxy_client_socket.h b/net/spdy/spdy_proxy_client_socket.h deleted file mode 100644 index 30062b0..0000000 --- a/net/spdy/spdy_proxy_client_socket.h +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_SPDY_SPDY_PROXY_CLIENT_SOCKET_H_ -#define NET_SPDY_SPDY_PROXY_CLIENT_SOCKET_H_ -#pragma once - -#include <string> -#include <list> - -#include "base/basictypes.h" -#include "base/ref_counted.h" -#include "net/base/completion_callback.h" -#include "net/base/host_port_pair.h" -#include "net/base/net_log.h" -#include "net/http/http_auth_controller.h" -#include "net/http/http_request_headers.h" -#include "net/http/http_request_info.h" -#include "net/http/http_response_info.h" -#include "net/socket/client_socket.h" -#include "net/spdy/spdy_protocol.h" -#include "net/spdy/spdy_session.h" -#include "net/spdy/spdy_stream.h" - - -class GURL; - -namespace net { - -class AddressList; -class ClientSocketHandle; -class HttpStream; -class IOBuffer; -class SpdySession; -class SpdyStream; - -class SpdyProxyClientSocket : public ClientSocket, public SpdyStream::Delegate { - public: - // Create a socket on top of the |spdy_stream| by sending a SYN_STREAM - // CONNECT frame for |endpoint|. After the SYN_REPLY is received, - // any data read/written to the socket will be transferred in data - // frames. - SpdyProxyClientSocket(SpdyStream* spdy_stream, - const std::string& user_agent, - const HostPortPair& endpoint, - const GURL& url, - const HostPortPair& proxy_server, - HttpAuthCache* auth_cache, - HttpAuthHandlerFactory* auth_handler_factory); - - - // On destruction Disconnect() is called. - virtual ~SpdyProxyClientSocket(); - - const scoped_refptr<HttpAuthController>& auth_controller() { - return auth_; - } - - const HttpResponseInfo* GetConnectResponseInfo() const { - return response_.headers ? &response_ : NULL; - } - - // ClientSocket methods: - - virtual int Connect(CompletionCallback* callback); - virtual void Disconnect(); - virtual bool IsConnected() const; - virtual bool IsConnectedAndIdle() const; - virtual const BoundNetLog& NetLog() const { return net_log_; } - virtual void SetSubresourceSpeculation(); - virtual void SetOmniboxSpeculation(); - virtual bool WasEverUsed() const; - - // Socket methods: - - virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback); - virtual int Write(IOBuffer* buf, int buf_len, CompletionCallback* callback); - - virtual bool SetReceiveBufferSize(int32 size); - virtual bool SetSendBufferSize(int32 size); - - virtual int GetPeerAddress(AddressList* address) const; - - // SpdyStream::Delegate methods: - - // Called when SYN frame has been sent. - // Returns true if no more data to be sent after SYN frame. - virtual bool OnSendHeadersComplete(int status); - - // Called when stream is ready to send data. - // Returns network error code. OK when it successfully sent data. - virtual int OnSendBody(); - - // Called when data has been sent. |status| indicates network error - // or number of bytes has been sent. - // Returns true if no more data to be sent. - virtual bool OnSendBodyComplete(int status); - - // Called when SYN_STREAM or SYN_REPLY received. |status| indicates network - // error. Returns network error code. - virtual int OnResponseReceived(const spdy::SpdyHeaderBlock& response, - base::Time response_time, - int status); - - // Called when data is received. - virtual void OnDataReceived(const char* data, int length); - - // Called when data is sent. - virtual void OnDataSent(int length); - - // Called when SpdyStream is closed. - virtual void OnClose(int status); - - private: - enum State { - STATE_NONE, - STATE_GENERATE_AUTH_TOKEN, - STATE_GENERATE_AUTH_TOKEN_COMPLETE, - STATE_SEND_REQUEST, - STATE_SEND_REQUEST_COMPLETE, - STATE_READ_REPLY_COMPLETE, - STATE_DONE, - }; - - void OnIOComplete(int result); - - int DoLoop(int last_io_result); - int DoGenerateAuthToken(); - int DoGenerateAuthTokenComplete(int result); - int DoSendRequest(); - int DoSendRequestComplete(int result); - int DoReadReplyComplete(int result); - - // Populates |user_buffer_| with as much read data as possible - // and returns the number of bytes read. - int PopulateUserReadBuffer(); - - CompletionCallbackImpl<SpdyProxyClientSocket> io_callback_; - State next_state_; - - // Pointer to the SPDY Stream that this sits on top of. - scoped_refptr<SpdyStream> spdy_stream_; - - // Stores the callback to the layer above, called on completing Read() or - // Connect(). - CompletionCallback* read_callback_; - // Stores the callback to the layer above, called on completing Write(). - CompletionCallback* write_callback_; - - // CONNECT request and response. - HttpRequestInfo request_; - HttpResponseInfo response_; - - // The hostname and port of the endpoint. This is not necessarily the one - // specified by the URL, due to Alternate-Protocol or fixed testing ports. - const HostPortPair endpoint_; - scoped_refptr<HttpAuthController> auth_; - - // We buffer the response body as it arrives asynchronously from the stream. - std::list<scoped_refptr<DrainableIOBuffer> > read_buffer_; - - // User provided buffer for the Read() response. - scoped_refptr<DrainableIOBuffer> user_buffer_; - - // User specified number of bytes to be written. - int write_buffer_len_; - // Number of bytes written which have not been confirmed - int write_bytes_outstanding_; - - // True if read has ever returned zero for eof. - bool eof_has_been_read_; - // True if the transport socket has ever sent data. - bool was_ever_used_; - - const BoundNetLog net_log_; - - DISALLOW_COPY_AND_ASSIGN(SpdyProxyClientSocket); -}; - -} // namespace net - -#endif // NET_SPDY_SPDY_PROXY_CLIENT_SOCKET_H_ diff --git a/net/spdy/spdy_proxy_client_socket_unittest.cc b/net/spdy/spdy_proxy_client_socket_unittest.cc deleted file mode 100644 index edde8a5..0000000 --- a/net/spdy/spdy_proxy_client_socket_unittest.cc +++ /dev/null @@ -1,894 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/spdy/spdy_proxy_client_socket.h" - -#include "base/utf_string_conversions.h" -#include "net/base/address_list.h" -#include "net/base/net_log.h" -#include "net/base/net_log_unittest.h" -#include "net/base/mock_host_resolver.h" -#include "net/base/test_completion_callback.h" -#include "net/base/winsock_init.h" -#include "net/http/http_response_info.h" -#include "net/http/http_response_headers.h" -#include "net/socket/client_socket_factory.h" -#include "net/socket/tcp_client_socket.h" -#include "net/socket/socket_test_util.h" -#include "net/spdy/spdy_protocol.h" -#include "net/spdy/spdy_session_pool.h" -#include "net/spdy/spdy_test_util.h" -#include "testing/platform_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -//----------------------------------------------------------------------------- - -namespace { - -static const char kUrl[] = "https://www.google.com/"; -static const char kOriginHost[] = "www.google.com"; -static const int kOriginPort = 443; -static const char kOriginHostPort[] = "www.google.com:443"; -static const char kProxyUrl[] = "http://myproxy:6121/"; -static const char kProxyHost[] = "myproxy"; -static const int kProxyPort = 6121; -static const char kUserAgent[] = "Mozilla/1.0"; - -static const int kStreamId = 1; - -static const char kMsg1[] = "\0hello!\xff"; -static const int kLen1 = 8; -static const char kMsg2[] = "\012345678\0"; -static const int kLen2 = 10; -static const char kMsg3[] = "bye!"; -static const int kLen3 = 4; -static const char kMsg33[] = "bye!bye!"; -static const int kLen33 = kLen3 + kLen3; - -} // anonymous namespace - -namespace net { - -class SpdyProxyClientSocketTest : public PlatformTest { - public: - SpdyProxyClientSocketTest(); - - virtual void TearDown(); - - protected: - void Initialize(MockRead* reads, size_t reads_count, MockWrite* writes, - size_t writes_count); - spdy::SpdyFrame* ConstructConnectRequestFrame(); - spdy::SpdyFrame* ConstructConnectAuthRequestFrame(); - spdy::SpdyFrame* ConstructConnectReplyFrame(); - spdy::SpdyFrame* ConstructConnectAuthReplyFrame(); - spdy::SpdyFrame* ConstructConnectErrorReplyFrame(); - spdy::SpdyFrame* ConstructBodyFrame(const char* data, int length); - scoped_refptr<IOBufferWithSize> CreateBuffer(const char* data, int size); - void AssertConnectSucceeds(); - void AssertConnectionEstablished(); - void AssertSyncReadEquals(const char* data, int len); - void AssertAsyncReadEquals(const char* data, int len); - void AssertAsyncWriteSucceeds(const char* data, int len); - void AssertAsyncWriteWithReadsSucceeds(const char* data, int len, - int num_reads); - - void AddAuthToCache() { - const string16 kFoo(ASCIIToUTF16("foo")); - const string16 kBar(ASCIIToUTF16("bar")); - session_->auth_cache()->Add(GURL(kProxyUrl), "MyRealm1", "Basic", - "Basic realm=MyRealm1", kFoo, kBar, "/"); - } - - scoped_ptr<SpdyProxyClientSocket> sock_; - TestCompletionCallback callback_; - - private: - scoped_refptr<HttpNetworkSession> session_; - scoped_refptr<OrderedSocketData> data_; - SpdySessionDependencies session_deps_; - MockConnect connect_data_; - scoped_refptr<SpdySession> spdy_session_; - scoped_refptr<SpdyStream> spdy_stream_; - spdy::SpdyFramer framer_; - - std::string user_agent_; - GURL url_; - HostPortPair proxy_host_port_; - HostPortPair endpoint_host_port_pair_; - ProxyServer proxy_; - HostPortProxyPair endpoint_host_port_proxy_pair_; - scoped_refptr<TCPSocketParams> tcp_params_; - - DISALLOW_COPY_AND_ASSIGN(SpdyProxyClientSocketTest); -}; - -SpdyProxyClientSocketTest::SpdyProxyClientSocketTest() - : sock_(NULL), - callback_(), - session_(NULL), - data_(NULL), - session_deps_(), - connect_data_(false, OK), - spdy_session_(NULL), - spdy_stream_(NULL), - framer_(), - user_agent_(kUserAgent), - url_(kUrl), - proxy_host_port_(kProxyHost, kProxyPort), - endpoint_host_port_pair_(kOriginHost, kOriginPort), - proxy_(ProxyServer::SCHEME_HTTPS, proxy_host_port_), - endpoint_host_port_proxy_pair_(endpoint_host_port_pair_, proxy_), - tcp_params_(new TCPSocketParams(proxy_host_port_, LOWEST, url_, false)) { -} - -void SpdyProxyClientSocketTest::TearDown() { - if (session_ != NULL) - session_->spdy_session_pool()->CloseAllSessions(); - - spdy::SpdyFramer::set_enable_compression_default(true); - // Empty the current queue. - MessageLoop::current()->RunAllPending(); - PlatformTest::TearDown(); -} - -void SpdyProxyClientSocketTest::Initialize(MockRead* reads, - size_t reads_count, - MockWrite* writes, - size_t writes_count) { - data_ = new OrderedSocketData(reads, reads_count, writes, writes_count); - data_->set_connect_data(connect_data_); - - session_deps_.socket_factory->AddSocketDataProvider(data_.get()); - session_deps_.host_resolver->set_synchronous_mode(true); - - session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_); - SpdySession::SetSSLMode(false); - spdy::SpdyFramer::set_enable_compression_default(false); - - // Creates a new spdy session - spdy_session_ = - session_->spdy_session_pool()->Get(endpoint_host_port_proxy_pair_, - session_->mutable_spdy_settings(), - BoundNetLog()); - - // Perform the TCP connect - scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); - EXPECT_EQ(OK, - connection->Init(endpoint_host_port_pair_.ToString(), tcp_params_, - LOWEST, NULL, session_->tcp_socket_pool(), - BoundNetLog())); - spdy_session_->InitializeWithSocket(connection.release(), false, OK); - - // Create the SPDY Stream - ASSERT_EQ( - OK, - spdy_session_->CreateStream(url_, LOWEST, &spdy_stream_, BoundNetLog(), - NULL)); - - // Create the SpdyProxyClientSocket - sock_.reset( - new SpdyProxyClientSocket(spdy_stream_, user_agent_, - endpoint_host_port_pair_, url_, - proxy_host_port_, session_->auth_cache(), - session_->http_auth_handler_factory())); -} - -scoped_refptr<IOBufferWithSize> SpdyProxyClientSocketTest::CreateBuffer( - const char* data, int size) { - scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(size)); - memcpy(buf->data(), data, size); - return buf; -} - -void SpdyProxyClientSocketTest::AssertConnectSucceeds() { - ASSERT_EQ(ERR_IO_PENDING, sock_->Connect(&callback_)); - ASSERT_EQ(OK, callback_.WaitForResult()); -} - -void SpdyProxyClientSocketTest::AssertConnectionEstablished() { - const HttpResponseInfo* response = sock_->GetConnectResponseInfo(); - ASSERT_TRUE(response != NULL); - ASSERT_EQ(200, response->headers->response_code()); - ASSERT_EQ("Connection Established", response->headers->GetStatusText()); -} - -void SpdyProxyClientSocketTest::AssertSyncReadEquals(const char* data, - int len) { - scoped_refptr<IOBuffer> buf(new IOBuffer(len)); - ASSERT_EQ(len, sock_->Read(buf, len, NULL)); - ASSERT_EQ(std::string(data, len), std::string(buf->data(), len)); - ASSERT_TRUE(sock_->IsConnected()); -} - -void SpdyProxyClientSocketTest::AssertAsyncReadEquals(const char* data, - int len) { - // Issue the read, which will be completed asynchronously - scoped_refptr<IOBuffer> buf(new IOBuffer(len)); - ASSERT_EQ(ERR_IO_PENDING, sock_->Read(buf, len, &callback_)); - EXPECT_TRUE(sock_->IsConnected()); - - // Dummy write to un-block the read - AssertAsyncWriteSucceeds(kMsg2, kLen2); - EXPECT_TRUE(sock_->IsConnected()); - - // Now the read will return - EXPECT_EQ(len, callback_.WaitForResult()); - ASSERT_EQ(std::string(data, len), std::string(buf->data(), len)); -} - -void SpdyProxyClientSocketTest::AssertAsyncWriteSucceeds(const char* data, - int len) { - AssertAsyncWriteWithReadsSucceeds(data, len, 0); -} - -void SpdyProxyClientSocketTest::AssertAsyncWriteWithReadsSucceeds( - const char* data, int len, int num_reads) { - scoped_refptr<IOBufferWithSize> buf(CreateBuffer(data, len)); - - TestCompletionCallback callback; - EXPECT_EQ(ERR_IO_PENDING, sock_->Write(buf, buf->size(), &callback)); - - // Dummy reads to un-block the writes - for (int i = 0; i < num_reads; i++) { - AssertSyncReadEquals(kMsg2, kLen2); - } - - callback.WaitForResult(); -} - -// Constructs a standard SPDY SYN_STREAM frame for a CONNECT request. -spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectRequestFrame() { - const SpdyHeaderInfo kSynStartHeader = { - spdy::SYN_STREAM, - kStreamId, - 0, - net::ConvertRequestPriorityToSpdyPriority(LOWEST), - spdy::CONTROL_FLAG_NONE, - false, - spdy::INVALID, - NULL, - 0, - spdy::DATA_FLAG_NONE - }; - const char* const kConnectHeaders[] = { - "method", "CONNECT", - "url", kOriginHostPort, - "host", kOriginHost, - "user-agent", kUserAgent, - "version", "HTTP/1.1", - "proxy-connection", "keep-alive", - }; - return ConstructSpdyPacket( - kSynStartHeader, NULL, 0, kConnectHeaders, arraysize(kConnectHeaders)/2); -} - -// Constructs a SPDY SYN_STREAM frame for a CONNECT request which includes -// Proxy-Authorization headers. -spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectAuthRequestFrame() { - const SpdyHeaderInfo kSynStartHeader = { - spdy::SYN_STREAM, - kStreamId, - 0, - net::ConvertRequestPriorityToSpdyPriority(LOWEST), - spdy::CONTROL_FLAG_NONE, - false, - spdy::INVALID, - NULL, - 0, - spdy::DATA_FLAG_NONE - }; - const char* const kConnectHeaders[] = { - "method", "CONNECT", - "url", kOriginHostPort, - "host", kOriginHost, - "user-agent", kUserAgent, - "version", "HTTP/1.1", - "proxy-authorization", "Basic Zm9vOmJhcg==", - "proxy-connection", "keep-alive", - }; - return ConstructSpdyPacket( - kSynStartHeader, NULL, 0, kConnectHeaders, arraysize(kConnectHeaders)/2); -} - -// Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT. -spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectReplyFrame() { - const char* const kStandardReplyHeaders[] = { - "status", "200 Connection Established", - "version", "HTTP/1.1" - }; - return ConstructSpdyControlFrame(NULL, - 0, - false, - kStreamId, - LOWEST, - spdy::SYN_REPLY, - spdy::CONTROL_FLAG_NONE, - kStandardReplyHeaders, - arraysize(kStandardReplyHeaders)); -} - -// Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT. -spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectAuthReplyFrame() { - const char* const kStandardReplyHeaders[] = { - "status", "407 Proxy Authentication Required", - "version", "HTTP/1.1", - "proxy-authenticate", "Basic realm=\"MyRealm1\"", - }; - - return ConstructSpdyControlFrame(NULL, - 0, - false, - kStreamId, - LOWEST, - spdy::SYN_REPLY, - spdy::CONTROL_FLAG_NONE, - kStandardReplyHeaders, - arraysize(kStandardReplyHeaders)); -} - -// Constructs a SPDY SYN_REPLY frame with an HTTP 500 error. -spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectErrorReplyFrame() { - const char* const kStandardReplyHeaders[] = { - "status", "500 Internal Server Error", - "version", "HTTP/1.1", - }; - - return ConstructSpdyControlFrame(NULL, - 0, - false, - kStreamId, - LOWEST, - spdy::SYN_REPLY, - spdy::CONTROL_FLAG_NONE, - kStandardReplyHeaders, - arraysize(kStandardReplyHeaders)); -} - -spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructBodyFrame(const char* data, - int length) { - return framer_.CreateDataFrame(kStreamId, data, length, spdy::DATA_FLAG_NONE); -} - -// ----------- Connect - -TEST_F(SpdyProxyClientSocketTest, ConnectSendsCorrectRequest) { - scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); - MockWrite writes[] = { - CreateMockWrite(*conn, 0), - }; - - scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); - MockRead reads[] = { - CreateMockRead(*resp, 1), - MockRead(true, 0, 0), // EOF - }; - - Initialize(reads, arraysize(reads), writes, arraysize(writes)); - - ASSERT_FALSE(sock_->IsConnected()); - - AssertConnectSucceeds(); - - AssertConnectionEstablished(); -} - -TEST_F(SpdyProxyClientSocketTest, ConnectWithAuthRequested) { - scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); - MockWrite writes[] = { - CreateMockWrite(*conn, 0), - }; - - scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectAuthReplyFrame()); - MockRead reads[] = { - CreateMockRead(*resp, 1), - MockRead(true, 0, 0), // EOF - }; - - Initialize(reads, arraysize(reads), writes, arraysize(writes)); - - EXPECT_EQ(ERR_IO_PENDING, sock_->Connect(&callback_)); - EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, callback_.WaitForResult()); - - const HttpResponseInfo* response = sock_->GetConnectResponseInfo(); - ASSERT_TRUE(response != NULL); - ASSERT_EQ(407, response->headers->response_code()); - ASSERT_EQ("Proxy Authentication Required", - response->headers->GetStatusText()); -} - -TEST_F(SpdyProxyClientSocketTest, ConnectWithAuthCredentials) { - scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectAuthRequestFrame()); - MockWrite writes[] = { - CreateMockWrite(*conn, 0), - }; - - scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); - MockRead reads[] = { - CreateMockRead(*resp, 1), - MockRead(true, 0, 0), // EOF - }; - - Initialize(reads, arraysize(reads), writes, arraysize(writes)); - AddAuthToCache(); - - EXPECT_EQ(ERR_IO_PENDING, sock_->Connect(&callback_)); - EXPECT_EQ(OK, callback_.WaitForResult()); - - AssertConnectionEstablished(); -} - -TEST_F(SpdyProxyClientSocketTest, ConnectFails) { - scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); - MockWrite writes[] = { - CreateMockWrite(*conn, 0), - }; - - scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); - MockRead reads[] = { - MockRead(true, 0, 0), // EOF - }; - - Initialize(reads, arraysize(reads), writes, arraysize(writes)); - - ASSERT_FALSE(sock_->IsConnected()); - - ASSERT_EQ(ERR_IO_PENDING, sock_->Connect(&callback_)); - ASSERT_EQ(ERR_CONNECTION_CLOSED, callback_.WaitForResult()); - - ASSERT_FALSE(sock_->IsConnected()); -} - -// ----------- WasEverUsed - -TEST_F(SpdyProxyClientSocketTest, WasEverUsedReturnsCorrectValues) { - scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); - MockWrite writes[] = { - CreateMockWrite(*conn, 0), - }; - - scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); - MockRead reads[] = { - CreateMockRead(*resp, 1), - MockRead(true, 0, 0), // EOF - }; - - Initialize(reads, arraysize(reads), writes, arraysize(writes)); - - EXPECT_FALSE(sock_->WasEverUsed()); - AssertConnectSucceeds(); - EXPECT_TRUE(sock_->WasEverUsed()); - sock_->Disconnect(); - EXPECT_TRUE(sock_->WasEverUsed()); -} - -// ----------- GetPeerAddress - -TEST_F(SpdyProxyClientSocketTest, GetPeerAddressReturnsCorrectValues) { - scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); - MockWrite writes[] = { - CreateMockWrite(*conn, 1), - MockWrite(true, 0, 3), // EOF - }; - - scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); - MockRead reads[] = { - CreateMockRead(*resp, 2), - MockRead(false, 0, 4), // EOF - }; - - Initialize(reads, arraysize(reads), writes, arraysize(writes)); - - net::AddressList addr; - EXPECT_EQ(ERR_UNEXPECTED, sock_->GetPeerAddress(&addr)); - AssertConnectSucceeds(); - EXPECT_TRUE(sock_->IsConnected()); - EXPECT_EQ(OK, sock_->GetPeerAddress(&addr)); - sock_->Disconnect(); - EXPECT_EQ(ERR_UNEXPECTED, sock_->GetPeerAddress(&addr)); -} - -// ----------- Write - -TEST_F(SpdyProxyClientSocketTest, WriteSendsDataInDataFrame) { - scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); - scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); - scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); - MockWrite writes[] = { - CreateMockWrite(*conn, 0), - CreateMockWrite(*msg1, 3), - CreateMockWrite(*msg2, 4), - }; - - scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); - MockRead reads[] = { - CreateMockRead(*resp, 2), - MockRead(true, 0, 6), // EOF - }; - - Initialize(reads, arraysize(reads), writes, arraysize(writes)); - - AssertConnectSucceeds(); - - AssertAsyncWriteSucceeds(kMsg1, kLen1); - AssertAsyncWriteSucceeds(kMsg2, kLen2); -} - -// ----------- Read - -TEST_F(SpdyProxyClientSocketTest, ReadReadsDataInDataFrame) { - scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); - MockWrite writes[] = { - CreateMockWrite(*conn, 1), - }; - - scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); - scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); - scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); - MockRead reads[] = { - CreateMockRead(*resp, 2), - CreateMockRead(*msg1, 3), - CreateMockRead(*msg2, 4), - MockRead(true, 0, 6), // EOF - }; - - Initialize(reads, arraysize(reads), writes, arraysize(writes)); - - AssertConnectSucceeds(); - - AssertSyncReadEquals(kMsg1, kLen1); - AssertSyncReadEquals(kMsg2, kLen2); -} - -TEST_F(SpdyProxyClientSocketTest, ReadAuthResponseBody) { - scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); - MockWrite writes[] = { - CreateMockWrite(*conn, 1), - }; - - scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectAuthReplyFrame()); - scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); - scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); - MockRead reads[] = { - CreateMockRead(*resp, 2), - CreateMockRead(*msg1, 3), - CreateMockRead(*msg2, 4), - MockRead(true, 0, 6), // EOF - }; - - Initialize(reads, arraysize(reads), writes, arraysize(writes)); - - EXPECT_EQ(ERR_IO_PENDING, sock_->Connect(&callback_)); - EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, callback_.WaitForResult()); - // EXPECT_EQ(ERR_PROXY_AUTH_REQUESTED, callback_.WaitForResult()); - - AssertSyncReadEquals(kMsg1, kLen1); - AssertSyncReadEquals(kMsg2, kLen2); -} - -TEST_F(SpdyProxyClientSocketTest, ReadErrorResponseBody) { - scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); - MockWrite writes[] = { - CreateMockWrite(*conn, 1), - }; - - scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectErrorReplyFrame()); - scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); - scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); - MockRead reads[] = { - CreateMockRead(*resp, 2), - CreateMockRead(*msg1, 3), - CreateMockRead(*msg2, 4), - MockRead(true, 0, 6), // EOF - }; - - Initialize(reads, arraysize(reads), writes, arraysize(writes)); - - EXPECT_EQ(ERR_IO_PENDING, sock_->Connect(&callback_)); - EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, callback_.WaitForResult()); - - AssertSyncReadEquals(kMsg1, kLen1); - AssertSyncReadEquals(kMsg2, kLen2); -} - -// ----------- Reads and Writes - -TEST_F(SpdyProxyClientSocketTest, AsyncReadAroundWrite) { - scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); - scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); - MockWrite writes[] = { - CreateMockWrite(*conn, 1), - CreateMockWrite(*msg2, 4), // write to un-cork the read - }; - - scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); - scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); - scoped_ptr<spdy::SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3)); - MockRead reads[] = { - CreateMockRead(*resp, 2), - CreateMockRead(*msg1, 3), // sync read - CreateMockRead(*msg3, 5, true), // async read - MockRead(true, 0, 9), // EOF - }; - - Initialize(reads, arraysize(reads), writes, arraysize(writes)); - - AssertConnectSucceeds(); - - AssertSyncReadEquals(kMsg1, kLen1); - - AssertAsyncReadEquals(kMsg3, kLen3); -} - -TEST_F(SpdyProxyClientSocketTest, AsyncWriteAroundRead) { - scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); - scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); - MockWrite writes[] = { - CreateMockWrite(*conn, 1), - CreateMockWrite(*msg1, 4), - }; - - scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); - scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); - MockRead reads[] = { - CreateMockRead(*resp, 2), - CreateMockRead(*msg2, 3), // sync read (which will un-cork the write) - MockRead(true, 0, 5), // EOF - }; - - Initialize(reads, arraysize(reads), writes, arraysize(writes)); - - AssertConnectSucceeds(); - - AssertAsyncWriteWithReadsSucceeds(kMsg1, kLen1, 1); -} - -TEST_F(SpdyProxyClientSocketTest, Mixed) { - scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); - scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); - MockWrite writes[] = { - CreateMockWrite(*conn, 1), - CreateMockWrite(*msg2, 4), // write to un-cork the read - }; - - scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); - scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); - scoped_ptr<spdy::SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3)); - MockRead reads[] = { - CreateMockRead(*resp, 2), - CreateMockRead(*msg1, 3), // sync read - CreateMockRead(*msg3, 5, true), // async read - MockRead(true, 0, 9), // EOF - }; - - Initialize(reads, arraysize(reads), writes, arraysize(writes)); - - AssertConnectSucceeds(); - - AssertSyncReadEquals(kMsg1, kLen1); - AssertAsyncReadEquals(kMsg3, kLen3); -} - -TEST_F(SpdyProxyClientSocketTest, MultipleShortReads) { - scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); - MockWrite writes[] = { - CreateMockWrite(*conn, 1), - }; - - scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); - scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); - scoped_ptr<spdy::SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3)); - MockRead reads[] = { - CreateMockRead(*resp, 2), - CreateMockRead(*msg1, 3), // sync read - CreateMockRead(*msg3, 4), // sync read - CreateMockRead(*msg3, 5), // sync read - MockRead(true, 0, 8), // EOF - }; - - Initialize(reads, arraysize(reads), writes, arraysize(writes)); - - AssertConnectSucceeds(); - - AssertSyncReadEquals(kMsg1, kLen1); - // The payload from two data frames, each with kMsg3 will be combined - // together into a single read(). - AssertSyncReadEquals(kMsg33, kLen33); -} - -TEST_F(SpdyProxyClientSocketTest, MultipleShortReadsThenMoreRead) { - scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); - MockWrite writes[] = { - CreateMockWrite(*conn, 1), - }; - - scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); - scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); - scoped_ptr<spdy::SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3)); - scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); - MockRead reads[] = { - CreateMockRead(*resp, 2), - CreateMockRead(*msg1, 3), // sync read - CreateMockRead(*msg3, 4), // sync read - CreateMockRead(*msg3, 5), // sync read - CreateMockRead(*msg2, 5), // sync read - MockRead(true, 0, 8), // EOF - }; - - Initialize(reads, arraysize(reads), writes, arraysize(writes)); - - AssertConnectSucceeds(); - - AssertSyncReadEquals(kMsg1, kLen1); - // The payload from two data frames, each with kMsg3 will be combined - // together into a single read(). - AssertSyncReadEquals(kMsg33, kLen33); - AssertSyncReadEquals(kMsg2, kLen2); -} - - -TEST_F(SpdyProxyClientSocketTest, LargeSplitRead) { - scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); - MockWrite writes[] = { - CreateMockWrite(*conn, 1), - }; - - scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); - scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); - scoped_ptr<spdy::SpdyFrame> msg33(ConstructBodyFrame(kMsg33, kLen33)); - scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); - MockRead reads[] = { - CreateMockRead(*resp, 2), - CreateMockRead(*msg1, 3), - CreateMockRead(*msg33, 4), - MockRead(true, 0, 8), // EOF - }; - - Initialize(reads, arraysize(reads), writes, arraysize(writes)); - - AssertConnectSucceeds(); - - AssertSyncReadEquals(kMsg1, kLen1); - // The payload from the single large data frame will be read across - // two different reads. - AssertSyncReadEquals(kMsg3, kLen3); - AssertSyncReadEquals(kMsg3, kLen3); -} - -TEST_F(SpdyProxyClientSocketTest, WriteLargeDataSplits) { - std::string chunk_data(kMaxSpdyFrameChunkSize, 'x'); - scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); - scoped_ptr<spdy::SpdyFrame> chunk(ConstructBodyFrame(chunk_data.data(), - chunk_data.length())); - MockWrite writes[] = { - CreateMockWrite(*conn, 1), - CreateMockWrite(*chunk, 3, false), - CreateMockWrite(*chunk, 4, false), - CreateMockWrite(*chunk, 5, false) - }; - - scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); - MockRead reads[] = { - CreateMockRead(*resp, 2), - MockRead(true, 0, 7), // EOF - }; - - Initialize(reads, arraysize(reads), writes, arraysize(writes)); - - AssertConnectSucceeds(); - - std::string big_data(kMaxSpdyFrameChunkSize * 3, 'x'); - AssertAsyncWriteSucceeds(big_data.data(), big_data.length()); -} - -// ----------- Reading/Writing on Closed socket - -// Reading from an already closed socket should return 0 -TEST_F(SpdyProxyClientSocketTest, ReadOnClosedSocketReturnsZero) { - scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); - MockWrite writes[] = { - CreateMockWrite(*conn, 1), - }; - - scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); - MockRead reads[] = { - CreateMockRead(*resp, 2), - MockRead(true, 0, 4), // EOF - }; - - Initialize(reads, arraysize(reads), writes, arraysize(writes)); - - AssertConnectSucceeds(); - - sock_->Disconnect(); - - ASSERT_EQ(0, sock_->Read(NULL, 1, NULL)); - ASSERT_EQ(ERR_CONNECTION_CLOSED, sock_->Read(NULL, 1, NULL)); - ASSERT_EQ(ERR_CONNECTION_CLOSED, sock_->Read(NULL, 1, NULL)); -} - -// Calling Write() on a closed socket is an error -TEST_F(SpdyProxyClientSocketTest, WriteOnClosedStream) { - scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); - MockWrite writes[] = { - CreateMockWrite(*conn, 1), - }; - - scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); - scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); - MockRead reads[] = { - CreateMockRead(*resp, 2), - MockRead(false, 0, 3), // EOF - }; - - Initialize(reads, arraysize(reads), writes, arraysize(writes)); - - AssertConnectSucceeds(); - - scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1)); - EXPECT_EQ(ERR_CONNECTION_CLOSED, sock_->Write(buf, buf->size(), NULL)); -} - -// ----------- Pending read/write when closed - -// If the socket is closed with a pending Write(), the callback -// should not be called. -TEST_F(SpdyProxyClientSocketTest, DisconnectWithWritePending) { - scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); - MockWrite writes[] = { - CreateMockWrite(*conn, 1), - MockWrite(true, 0, 3), // EOF - }; - - scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); - MockRead reads[] = { - CreateMockRead(*resp, 2), - MockRead(false, 0, 4), // EOF - }; - - Initialize(reads, arraysize(reads), writes, arraysize(writes)); - - AssertConnectSucceeds(); - - EXPECT_TRUE(sock_->IsConnected()); - - scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1)); - EXPECT_EQ(ERR_IO_PENDING, sock_->Write(buf, buf->size(), &callback_)); - - sock_->Disconnect(); - - EXPECT_FALSE(sock_->IsConnected()); - EXPECT_FALSE(callback_.have_result()); -} - -// If the socket is closed with a pending Read(), the callback -// should not be called. -TEST_F(SpdyProxyClientSocketTest, DisconnectWithReadPending) { - scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); - MockWrite writes[] = { - CreateMockWrite(*conn, 1), - }; - - scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); - MockRead reads[] = { - CreateMockRead(*resp, 2), - MockRead(true, 0, 4), // EOF - }; - - Initialize(reads, arraysize(reads), writes, arraysize(writes)); - - AssertConnectSucceeds(); - - EXPECT_TRUE(sock_->IsConnected()); - - scoped_refptr<IOBuffer> buf(new IOBuffer(kLen1)); - ASSERT_EQ(ERR_IO_PENDING, sock_->Read(buf, kLen1, &callback_)); - - sock_->Disconnect(); - - EXPECT_FALSE(sock_->IsConnected()); - EXPECT_FALSE(callback_.have_result()); -} - -} // namespace net diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h index 49de547..2894471 100644 --- a/net/spdy/spdy_session.h +++ b/net/spdy/spdy_session.h @@ -158,12 +158,6 @@ class SpdySession : public base::RefCounted<SpdySession>, return frames_received_ > 0; } - // Returns true if the underlying transport socket ever had any reads or - // writes. - bool WasEverUsed() const { - return connection_->socket()->WasEverUsed(); - } - void set_in_session_pool(bool val) { in_session_pool_ = val; } // Access to the number of active and pending streams. These are primarily @@ -175,10 +169,6 @@ class SpdySession : public base::RefCounted<SpdySession>, const BoundNetLog& net_log() const { return net_log_; } - int GetPeerAddress(AddressList* address) const { - return connection_->socket()->GetPeerAddress(address); - } - private: friend class base::RefCounted<SpdySession>; FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, GetActivePushStream); diff --git a/net/spdy/spdy_stream.cc b/net/spdy/spdy_stream.cc index 102d318..88b009d 100644 --- a/net/spdy/spdy_stream.cc +++ b/net/spdy/spdy_stream.cc @@ -205,13 +205,6 @@ void SpdyStream::DecreaseRecvWindowSize(int delta_window_size) { session_->ResetStream(stream_id_, spdy::FLOW_CONTROL_ERROR); } -int SpdyStream::GetPeerAddress(AddressList* address) const { - return session_->GetPeerAddress(address); -} - -bool SpdyStream::WasEverUsed() const { - return session_->WasEverUsed(); -} base::Time SpdyStream::GetRequestTime() const { return request_time_; diff --git a/net/spdy/spdy_stream.h b/net/spdy/spdy_stream.h index 4e30a60..1730af5 100644 --- a/net/spdy/spdy_stream.h +++ b/net/spdy/spdy_stream.h @@ -21,7 +21,6 @@ namespace net { -class AddressList; class SpdySession; class SSLCertRequestInfo; class SSLInfo; @@ -130,12 +129,6 @@ class SpdyStream : public base::RefCounted<SpdyStream> { // Decreases |send_window_size_| by the given number of bytes. void DecreaseSendWindowSize(int delta_window_size); - int GetPeerAddress(AddressList* address) const; - - // Returns true if the underlying transport socket ever had any reads or - // writes. - bool WasEverUsed() const; - // Increases |recv_window_size_| by the given number of bytes, also sends // a WINDOW_UPDATE frame. void IncreaseRecvWindowSize(int delta_window_size); |