summaryrefslogtreecommitdiffstats
path: root/net/spdy
diff options
context:
space:
mode:
authorrch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-17 03:58:29 +0000
committerrch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-17 03:58:29 +0000
commit511f6f525dacf2512439b12784186074a0f6cd5c (patch)
tree5fa90bbe0fa255de3d78d00dcffd333830e13aea /net/spdy
parent8aad42dcc8d683242c730901c51061de710046b9 (diff)
downloadchromium_src-511f6f525dacf2512439b12784186074a0f6cd5c.zip
chromium_src-511f6f525dacf2512439b12784186074a0f6cd5c.tar.gz
chromium_src-511f6f525dacf2512439b12784186074a0f6cd5c.tar.bz2
Allow a non-200 (or non-407) response for a CONNECT request from an HTTPS proxy
to be consumed by chrome. Among other things, this will allow the proxy to inform the user that the hostname could not be resolved or similar conditions. This adds a new OnHttpsProxyTunnelConnectionResponse method to StreamRequest::Delegate which is invoked when an HTTPS proxy returns a non-200, non-407 response. The method is called with an HttpResponseInfor argument to access the request headers, and an HttpStream argument to access the response body. BUG=none TEST=HttpNetworkTransactionTest Review URL: http://codereview.chromium.org/4935001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@69513 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/spdy')
-rw-r--r--net/spdy/spdy_http_stream.cc10
-rw-r--r--net/spdy/spdy_http_stream.h4
-rw-r--r--net/spdy/spdy_proxy_client_socket.cc21
-rw-r--r--net/spdy/spdy_proxy_client_socket.h17
-rw-r--r--net/spdy/spdy_proxy_client_socket_unittest.cc8
5 files changed, 50 insertions, 10 deletions
diff --git a/net/spdy/spdy_http_stream.cc b/net/spdy/spdy_http_stream.cc
index 75f8039..15acff7 100644
--- a/net/spdy/spdy_http_stream.cc
+++ b/net/spdy/spdy_http_stream.cc
@@ -21,7 +21,8 @@
namespace net {
-SpdyHttpStream::SpdyHttpStream(SpdySession* spdy_session, bool direct)
+SpdyHttpStream::SpdyHttpStream(SpdySession* spdy_session,
+ bool direct)
: ALLOW_THIS_IN_INITIALIZER_LIST(read_callback_factory_(this)),
stream_(NULL),
spdy_session_(spdy_session),
@@ -34,6 +35,12 @@ SpdyHttpStream::SpdyHttpStream(SpdySession* spdy_session, bool direct)
more_read_data_pending_(false),
direct_(direct) { }
+void SpdyHttpStream::InitializeWithExistingStream(SpdyStream* spdy_stream) {
+ stream_ = spdy_stream;
+ stream_->SetDelegate(this);
+ response_headers_received_ = true;
+}
+
SpdyHttpStream::~SpdyHttpStream() {
if (stream_)
stream_->DetachDelegate();
@@ -42,6 +49,7 @@ SpdyHttpStream::~SpdyHttpStream() {
int SpdyHttpStream::InitializeStream(const HttpRequestInfo* request_info,
const BoundNetLog& stream_net_log,
CompletionCallback* callback) {
+ DCHECK(!stream_.get());
if (spdy_session_->IsClosed())
return ERR_CONNECTION_CLOSED;
diff --git a/net/spdy/spdy_http_stream.h b/net/spdy/spdy_http_stream.h
index 76649b2..6e78379 100644
--- a/net/spdy/spdy_http_stream.h
+++ b/net/spdy/spdy_http_stream.h
@@ -31,10 +31,12 @@ class UploadDataStream;
// The SpdyHttpStream is a HTTP-specific type of stream known to a SpdySession.
class SpdyHttpStream : public SpdyStream::Delegate, public HttpStream {
public:
- // SpdyHttpStream constructor
SpdyHttpStream(SpdySession* spdy_session, bool direct);
virtual ~SpdyHttpStream();
+ // Initializes this SpdyHttpStream by wraping an existing SpdyStream.
+ void InitializeWithExistingStream(SpdyStream* spdy_stream);
+
SpdyStream* stream() { return stream_.get(); }
// Cancels any callbacks from being invoked and deletes the stream.
diff --git a/net/spdy/spdy_proxy_client_socket.cc b/net/spdy/spdy_proxy_client_socket.cc
index a6d209b..5beeeb3 100644
--- a/net/spdy/spdy_proxy_client_socket.cc
+++ b/net/spdy/spdy_proxy_client_socket.cc
@@ -59,6 +59,11 @@ SpdyProxyClientSocket::~SpdyProxyClientSocket() {
Disconnect();
}
+HttpStream* SpdyProxyClientSocket::CreateConnectResponseStream() {
+ DCHECK(response_stream_.get());
+ return response_stream_.release();
+}
+
// 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.
@@ -357,10 +362,22 @@ int SpdyProxyClientSocket::DoReadReplyComplete(int result) {
make_scoped_refptr(new NetLogHttpResponseParameter(response_.headers)));
}
- if (response_.headers->response_code() == 200)
+ if (response_.headers->response_code() == 200) {
return OK;
- else
+ } else if (response_.headers->response_code() == 407) {
return ERR_TUNNEL_CONNECTION_FAILED;
+ } else {
+ // Immediately hand off our SpdyStream to a newly created SpdyHttpStream
+ // so that any subsequent SpdyFrames are processed in the context of
+ // the HttpStream, not the socket.
+ DCHECK(spdy_stream_);
+ SpdyStream* stream = spdy_stream_;
+ spdy_stream_ = NULL;
+ response_stream_.reset(new SpdyHttpStream(NULL, false));
+ response_stream_->InitializeWithExistingStream(stream);
+ next_state_ = STATE_DISCONNECTED;
+ return ERR_HTTPS_PROXY_TUNNEL_RESPONSE;
+ }
}
// SpdyStream::Delegate methods:
diff --git a/net/spdy/spdy_proxy_client_socket.h b/net/spdy/spdy_proxy_client_socket.h
index 2becc75..e98dd9d 100644
--- a/net/spdy/spdy_proxy_client_socket.h
+++ b/net/spdy/spdy_proxy_client_socket.h
@@ -18,7 +18,8 @@
#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/http/proxy_client_socket.h"
+#include "net/spdy/spdy_http_stream.h"
#include "net/spdy/spdy_protocol.h"
#include "net/spdy/spdy_session.h"
#include "net/spdy/spdy_stream.h"
@@ -35,7 +36,8 @@ class IOBuffer;
class SpdySession;
class SpdyStream;
-class SpdyProxyClientSocket : public ClientSocket, public SpdyStream::Delegate {
+class SpdyProxyClientSocket : public ProxyClientSocket,
+ 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,
@@ -57,10 +59,17 @@ class SpdyProxyClientSocket : public ClientSocket, public SpdyStream::Delegate {
return auth_;
}
- const HttpResponseInfo* GetConnectResponseInfo() const {
+ // ProxyClientSocket methods:
+
+ virtual const HttpResponseInfo* GetConnectResponseInfo() const {
return response_.headers ? &response_ : NULL;
}
+ // In the event of a non-200 response to the CONNECT request, this
+ // method may be called to return an HttpStream in order to read
+ // the response body.
+ virtual HttpStream* CreateConnectResponseStream();
+
// ClientSocket methods:
virtual int Connect(CompletionCallback* callback);
virtual void Disconnect();
@@ -152,6 +161,8 @@ class SpdyProxyClientSocket : public ClientSocket, public SpdyStream::Delegate {
// True if the transport socket has ever sent data.
bool was_ever_used_;
+ scoped_ptr<SpdyHttpStream> response_stream_;
+
const BoundNetLog net_log_;
DISALLOW_COPY_AND_ASSIGN(SpdyProxyClientSocket);
diff --git a/net/spdy/spdy_proxy_client_socket_unittest.cc b/net/spdy/spdy_proxy_client_socket_unittest.cc
index 236713ac..c4c5f2c 100644
--- a/net/spdy/spdy_proxy_client_socket_unittest.cc
+++ b/net/spdy/spdy_proxy_client_socket_unittest.cc
@@ -839,12 +839,14 @@ TEST_F(SpdyProxyClientSocketTest, ReadErrorResponseBody) {
Initialize(reads, arraysize(reads), writes, arraysize(writes));
- AssertConnectFails(ERR_TUNNEL_CONNECTION_FAILED);
+ AssertConnectFails(ERR_HTTPS_PROXY_TUNNEL_RESPONSE);
Run(2); // SpdySession consumes the next two reads and sends then to
// sock_ to be buffered.
- AssertSyncReadEquals(kMsg1, kLen1);
- AssertSyncReadEquals(kMsg2, kLen2);
+ EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, sock_->Read(NULL, 1, NULL));
+ scoped_refptr<IOBuffer> buf(new IOBuffer(kLen1 + kLen2));
+ scoped_ptr<HttpStream> stream(sock_->CreateConnectResponseStream());
+ stream->ReadResponseBody(buf, kLen1 + kLen2, &read_callback_);
}
// ----------- Reads and Writes