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 /net/spdy/spdy_proxy_client_socket.cc | |
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
Diffstat (limited to 'net/spdy/spdy_proxy_client_socket.cc')
-rw-r--r-- | net/spdy/spdy_proxy_client_socket.cc | 437 |
1 files changed, 0 insertions, 437 deletions
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 |