Index: net/socket_stream/socket_stream.cc |
diff --git a/net/socket_stream/socket_stream.cc b/net/socket_stream/socket_stream.cc |
index 1dcf1f841dd3ca04852df51c2bd2c8ffda959bee..a74eb13decf62d632636d4d262dce3fe081f40b7 100644 |
--- a/net/socket_stream/socket_stream.cc |
+++ b/net/socket_stream/socket_stream.cc |
@@ -89,6 +89,7 @@ void SocketStream::Connect() { |
DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) << |
"The current MessageLoop must be TYPE_IO"; |
ssl_config_service()->GetSSLConfig(&ssl_config_); |
+ DCHECK_EQ(next_state_, STATE_NONE); |
AddRef(); // Released in Finish() |
// Open a connection asynchronously, so that delegate won't be called |
@@ -104,7 +105,7 @@ bool SocketStream::SendData(const char* data, int len) { |
"The current MessageLoop must exist"; |
DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) << |
"The current MessageLoop must be TYPE_IO"; |
- if (!socket_.get() || !socket_->IsConnected()) |
+ if (!socket_.get() || !socket_->IsConnected() || next_state_ == STATE_NONE) |
return false; |
if (write_buf_) { |
int current_amount_send = write_buf_size_ - write_buf_offset_; |
@@ -139,10 +140,10 @@ void SocketStream::Close() { |
"The current MessageLoop must exist"; |
DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) << |
"The current MessageLoop must be TYPE_IO"; |
- if (!socket_.get()) |
+ if (!socket_.get() || !socket_->IsConnected() || next_state_ == STATE_NONE) |
return; |
- if (socket_->IsConnected()) |
- socket_->Disconnect(); |
+ socket_->Disconnect(); |
+ next_state_ = STATE_CLOSE; |
// Close asynchronously, so that delegate won't be called |
// back before returning Close(). |
MessageLoop::current()->PostTask( |
@@ -182,18 +183,23 @@ void SocketStream::DetachDelegate() { |
Close(); |
} |
-void SocketStream::Finish() { |
+void SocketStream::Finish(int result) { |
DCHECK(MessageLoop::current()) << |
"The current MessageLoop must exist"; |
DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) << |
"The current MessageLoop must be TYPE_IO"; |
+ DCHECK_LT(result, 0); |
+ DCHECK_EQ(next_state_, STATE_NONE); |
DLOG(INFO) << "Finish"; |
+ if (delegate_) |
+ delegate_->OnError(this, result); |
+ |
Delegate* delegate = delegate_; |
delegate_ = NULL; |
if (delegate) { |
delegate->OnClose(this); |
- Release(); |
} |
+ Release(); |
} |
void SocketStream::SetHostResolver(HostResolver* host_resolver) { |
@@ -207,17 +213,16 @@ void SocketStream::SetClientSocketFactory( |
factory_ = factory; |
} |
-void SocketStream::DidEstablishConnection() { |
+int SocketStream::DidEstablishConnection() { |
if (!socket_.get() || !socket_->IsConnected()) { |
- Finish(); |
- return; |
+ return ERR_CONNECTION_FAILED; |
} |
next_state_ = STATE_READ_WRITE; |
if (delegate_) |
delegate_->OnConnected(this, max_pending_send_allowed_); |
- return; |
+ return OK; |
} |
void SocketStream::DidReceiveData(int result) { |
@@ -255,14 +260,12 @@ void SocketStream::DidSendData(int result) { |
void SocketStream::OnIOCompleted(int result) { |
DoLoop(result); |
- // TODO(ukai): notify error. |
} |
void SocketStream::OnReadCompleted(int result) { |
- // TODO(ukai): notify error. |
if (result == 0) { |
// 0 indicates end-of-file, so socket was closed. |
- next_state_ = STATE_NONE; |
+ next_state_ = STATE_CLOSE; |
} else if (result > 0 && read_buf_) { |
DidReceiveData(result); |
result = OK; |
@@ -271,7 +274,6 @@ void SocketStream::OnReadCompleted(int result) { |
} |
void SocketStream::OnWriteCompleted(int result) { |
- // TODO(ukai): notify error. |
if (result >= 0 && write_buf_) { |
DidSendData(result); |
result = OK; |
@@ -279,11 +281,9 @@ void SocketStream::OnWriteCompleted(int result) { |
DoLoop(result); |
} |
-int SocketStream::DoLoop(int result) { |
- if (next_state_ == STATE_NONE) { |
- Finish(); |
- return ERR_CONNECTION_CLOSED; |
- } |
+void SocketStream::DoLoop(int result) { |
+ if (next_state_ == STATE_NONE) |
+ return; |
do { |
State state = next_state_; |
@@ -341,17 +341,18 @@ int SocketStream::DoLoop(int result) { |
case STATE_READ_WRITE: |
result = DoReadWrite(result); |
break; |
+ case STATE_CLOSE: |
+ DCHECK_LE(result, OK); |
+ if (result == OK) |
+ result = ERR_CONNECTION_CLOSED; |
+ Finish(result); |
+ return; |
default: |
NOTREACHED() << "bad state"; |
result = ERR_UNEXPECTED; |
break; |
} |
- } while (result != ERR_IO_PENDING && next_state_ != STATE_NONE); |
- |
- if (result != ERR_IO_PENDING) |
- Finish(); |
- |
- return result; |
+ } while (result != ERR_IO_PENDING); |
} |
int SocketStream::DoResolveProxy() { |
@@ -368,6 +369,8 @@ int SocketStream::DoResolveProxyComplete(int result) { |
pac_request_ = NULL; |
if (result != OK) { |
LOG(ERROR) << "Failed to resolve proxy: " << result; |
+ if (delegate_) |
+ delegate_->OnError(this, result); |
proxy_info_.UseDirect(); |
} |
@@ -428,9 +431,9 @@ int SocketStream::DoTcpConnectComplete(int result) { |
else if (is_secure()) { |
next_state_ = STATE_SSL_CONNECT; |
} else { |
- DidEstablishConnection(); |
+ result = DidEstablishConnection(); |
} |
- return OK; |
+ return result; |
} |
int SocketStream::DoWriteTunnelHeaders() { |
@@ -532,8 +535,8 @@ int SocketStream::DoReadTunnelHeadersComplete(int result) { |
if (result == 0) { |
// 0 indicates end-of-file, so socket was closed. |
- Finish(); |
- return result; |
+ next_state_ = STATE_CLOSE; |
+ return ERR_CONNECTION_CLOSED; |
} |
tunnel_response_headers_len_ += result; |
@@ -542,8 +545,10 @@ int SocketStream::DoReadTunnelHeadersComplete(int result) { |
int eoh = HttpUtil::LocateEndOfHeaders( |
tunnel_response_headers_->headers(), tunnel_response_headers_len_, 0); |
if (eoh == -1) { |
- if (tunnel_response_headers_len_ >= kMaxTunnelResponseHeadersSize) |
+ if (tunnel_response_headers_len_ >= kMaxTunnelResponseHeadersSize) { |
+ next_state_ = STATE_CLOSE; |
return ERR_RESPONSE_HEADERS_TOO_BIG; |
+ } |
next_state_ = STATE_READ_TUNNEL_HEADERS; |
return OK; |
@@ -554,6 +559,7 @@ int SocketStream::DoReadTunnelHeadersComplete(int result) { |
HttpUtil::AssembleRawHeaders(tunnel_response_headers_->headers(), eoh)); |
if (headers->GetParsedHttpVersion() < HttpVersion(1, 0)) { |
// Require the "HTTP/1.x" status line. |
+ next_state_ = STATE_CLOSE; |
return ERR_TUNNEL_CONNECTION_FAILED; |
} |
switch (headers->response_code()) { |
@@ -562,7 +568,11 @@ int SocketStream::DoReadTunnelHeadersComplete(int result) { |
DCHECK_EQ(eoh, tunnel_response_headers_len_); |
next_state_ = STATE_SSL_CONNECT; |
} else { |
- DidEstablishConnection(); |
+ result = DidEstablishConnection(); |
+ if (result < 0) { |
+ next_state_ = STATE_CLOSE; |
+ return result; |
+ } |
if ((eoh < tunnel_response_headers_len_) && delegate_) |
delegate_->OnReceivedData( |
this, tunnel_response_headers_->headers() + eoh, |
@@ -583,6 +593,7 @@ int SocketStream::DoReadTunnelHeadersComplete(int result) { |
MessageLoop::current()->PostTask( |
FROM_HERE, |
NewRunnableMethod(this, &SocketStream::DoAuthRequired)); |
+ next_state_ = STATE_AUTH_REQUIRED; |
return ERR_IO_PENDING; |
} |
default: |
@@ -633,17 +644,15 @@ int SocketStream::DoSSLConnectComplete(int result) { |
result = HandleCertificateError(result); |
if (result == OK) |
- DidEstablishConnection(); |
+ result = DidEstablishConnection(); |
return result; |
} |
int SocketStream::DoReadWrite(int result) { |
if (result < OK) { |
- Finish(); |
return result; |
} |
if (!socket_.get() || !socket_->IsConnected()) { |
- Finish(); |
return ERR_CONNECTION_CLOSED; |
} |
@@ -658,7 +667,6 @@ int SocketStream::DoReadWrite(int result) { |
return OK; |
} else if (result == 0) { |
// 0 indicates end-of-file, so socket was closed. |
- Finish(); |
return ERR_CONNECTION_CLOSED; |
} |
// If read is pending, try write as well. |
@@ -746,6 +754,7 @@ void SocketStream::DoAuthRequired() { |
} |
void SocketStream::DoRestartWithAuth() { |
+ DCHECK_EQ(next_state_, STATE_AUTH_REQUIRED); |
auth_cache_.Add(ProxyAuthOrigin(), auth_handler_, |
auth_identity_.username, auth_identity_.password, |
std::string()); |