Index: net/spdy/spdy_proxy_client_socket.cc |
=================================================================== |
--- net/spdy/spdy_proxy_client_socket.cc (revision 62460) |
+++ net/spdy/spdy_proxy_client_socket.cc (working copy) |
@@ -30,7 +30,7 @@ |
HttpAuthHandlerFactory* auth_handler_factory) |
: ALLOW_THIS_IN_INITIALIZER_LIST( |
io_callback_(this, &SpdyProxyClientSocket::OnIOComplete)), |
- next_state_(STATE_NONE), |
+ next_state_(STATE_DISCONNECTED), |
spdy_stream_(spdy_stream), |
read_callback_(NULL), |
write_callback_(NULL), |
@@ -70,10 +70,10 @@ |
// the HTTPS Proxy tunnel failure from an HTTP Proxy tunnel failure. |
int SpdyProxyClientSocket::Connect(CompletionCallback* callback) { |
DCHECK(!read_callback_); |
- if (next_state_ == STATE_DONE) |
+ if (next_state_ == STATE_OPEN) |
return OK; |
- DCHECK_EQ(STATE_NONE, next_state_); |
+ DCHECK_EQ(STATE_DISCONNECTED, next_state_); |
next_state_ = STATE_GENERATE_AUTH_TOKEN; |
int rv = DoLoop(OK); |
@@ -83,7 +83,16 @@ |
} |
void SpdyProxyClientSocket::Disconnect() { |
- next_state_ = STATE_NONE; |
+ read_buffer_.clear(); |
+ user_buffer_ = NULL; |
+ read_callback_ = NULL; |
+ |
+ write_buffer_len_ = 0; |
+ write_bytes_outstanding_ = 0; |
+ write_callback_ = NULL; |
+ |
+ next_state_ = STATE_DISCONNECTED; |
+ |
if (spdy_stream_) |
// This will cause OnClose to be invoked, which takes care of |
// cleaning up all the internal state. |
@@ -91,8 +100,7 @@ |
} |
bool SpdyProxyClientSocket::IsConnected() const { |
- return next_state_ == STATE_DONE && spdy_stream_ != NULL && |
- !spdy_stream_->closed(); |
+ return next_state_ == STATE_OPEN || next_state_ == STATE_CLOSED; |
} |
bool SpdyProxyClientSocket::IsConnectedAndIdle() const { |
@@ -116,14 +124,17 @@ |
DCHECK(!read_callback_); |
DCHECK(!user_buffer_); |
- if (!spdy_stream_) { |
+ if (next_state_ == STATE_DISCONNECTED) |
+ return ERR_SOCKET_NOT_CONNECTED; |
+ |
+ if (!spdy_stream_ && read_buffer_.empty()) { |
if (eof_has_been_read_) |
return ERR_CONNECTION_CLOSED; |
eof_has_been_read_ = true; |
return 0; |
} |
- DCHECK(next_state_ == STATE_DONE); |
+ DCHECK(next_state_ == STATE_OPEN || next_state_ == STATE_CLOSED); |
DCHECK(buf); |
user_buffer_ = new DrainableIOBuffer(buf, buf_len); |
int result = PopulateUserReadBuffer(); |
@@ -146,7 +157,7 @@ |
data->BytesRemaining()); |
memcpy(user_buffer_->data(), data->data(), bytes_to_copy); |
user_buffer_->DidConsume(bytes_to_copy); |
- if (data->BytesRemaining() == 0) { |
+ if (data->BytesRemaining() == bytes_to_copy) { |
// Consumed all data from this buffer |
read_buffer_.pop_front(); |
} else { |
@@ -160,6 +171,9 @@ |
int SpdyProxyClientSocket::Write(IOBuffer* buf, int buf_len, |
CompletionCallback* callback) { |
DCHECK(!write_callback_); |
+ if (next_state_ == STATE_DISCONNECTED) |
+ return ERR_SOCKET_NOT_CONNECTED; |
+ |
if (!spdy_stream_) |
return ERR_CONNECTION_CLOSED; |
@@ -214,7 +228,7 @@ |
} |
void SpdyProxyClientSocket::OnIOComplete(int result) { |
- DCHECK_NE(STATE_NONE, next_state_); |
+ DCHECK_NE(STATE_DISCONNECTED, next_state_); |
int rv = DoLoop(result); |
if (rv != ERR_IO_PENDING) { |
CompletionCallback* c = read_callback_; |
@@ -224,11 +238,11 @@ |
} |
int SpdyProxyClientSocket::DoLoop(int last_io_result) { |
- DCHECK_NE(next_state_, STATE_NONE); |
+ DCHECK_NE(next_state_, STATE_DISCONNECTED); |
int rv = last_io_result; |
do { |
State state = next_state_; |
- next_state_ = STATE_NONE; |
+ next_state_ = STATE_DISCONNECTED; |
switch (state) { |
case STATE_GENERATE_AUTH_TOKEN: |
DCHECK_EQ(OK, rv); |
@@ -258,8 +272,8 @@ |
rv = ERR_UNEXPECTED; |
break; |
} |
- } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE && |
- next_state_ != STATE_DONE); |
+ } while (rv != ERR_IO_PENDING && next_state_ != STATE_DISCONNECTED && |
+ next_state_ != STATE_OPEN); |
return rv; |
} |
@@ -322,11 +336,11 @@ |
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; |
+ next_state_ = STATE_OPEN; |
if (net_log_.IsLoggingAll()) { |
net_log_.AddEvent( |
NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, |
@@ -417,21 +431,34 @@ |
void SpdyProxyClientSocket::OnClose(int status) { |
DCHECK(spdy_stream_); |
+ was_ever_used_ = spdy_stream_->WasEverUsed(); |
+ spdy_stream_ = NULL; |
+ |
+ bool connecting = next_state_ != STATE_DISCONNECTED && |
+ next_state_ < STATE_OPEN; |
+ if (next_state_ == STATE_OPEN) |
+ next_state_ = STATE_CLOSED; |
+ else |
+ next_state_ = STATE_DISCONNECTED; |
+ |
+ CompletionCallback* write_callback = write_callback_; |
+ write_callback_ = NULL; |
+ write_buffer_len_ = 0; |
+ write_bytes_outstanding_ = 0; |
+ |
// 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) { |
+ if (connecting) { |
DCHECK(read_callback_); |
- connect_callback = read_callback_; |
+ CompletionCallback* read_callback = read_callback_; |
+ read_callback_ = NULL; |
+ read_callback->Run(status); |
+ } else if (read_callback_) { |
+ // If we have a read_callback, the we need to make sure we call it back |
+ OnDataReceived(NULL, 0); |
} |
- 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); |
+ if (write_callback) |
+ write_callback->Run(ERR_CONNECTION_CLOSED); |
} |
} // namespace net |