| 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 | 
|  |