summaryrefslogtreecommitdiffstats
path: root/net/spdy/spdy_proxy_client_socket.cc
diff options
context:
space:
mode:
authorrch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-28 04:58:38 +0000
committerrch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-28 04:58:38 +0000
commit1c703210a2dbf7d5ff0ba06029e0411f0728c4e1 (patch)
treec6584610de9c306b6345f2395fdcd00bbf250c48 /net/spdy/spdy_proxy_client_socket.cc
parent06fb18592e5fad681cf33d80bae8a51862d8a923 (diff)
downloadchromium_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.cc437
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