diff options
-rw-r--r-- | net/socket_stream/socket_stream.cc | 79 | ||||
-rw-r--r-- | net/socket_stream/socket_stream.h | 18 |
2 files changed, 57 insertions, 40 deletions
diff --git a/net/socket_stream/socket_stream.cc b/net/socket_stream/socket_stream.cc index 1dcf1f8..a74eb13 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()); diff --git a/net/socket_stream/socket_stream.h b/net/socket_stream/socket_stream.h index c1aaf6e..37b723a 100644 --- a/net/socket_stream/socket_stream.h +++ b/net/socket_stream/socket_stream.h @@ -79,6 +79,11 @@ class SocketStream : public base::RefCountedThreadSafe<SocketStream> { // By default, no credential is available and close the connection. socket->Close(); } + + // Called when an error occured. + // This is only for error reporting to the delegate. + // |error| is net::Error. + virtual void OnError(const SocketStream* socket, int error) {} }; SocketStream(const GURL& url, Delegate* delegate); @@ -171,7 +176,9 @@ class SocketStream : public base::RefCountedThreadSafe<SocketStream> { STATE_SOCKS_CONNECT_COMPLETE, STATE_SSL_CONNECT, STATE_SSL_CONNECT_COMPLETE, - STATE_READ_WRITE + STATE_READ_WRITE, + STATE_AUTH_REQUIRED, + STATE_CLOSE, }; enum ProxyMode { @@ -184,11 +191,12 @@ class SocketStream : public base::RefCountedThreadSafe<SocketStream> { friend class base::RefCountedThreadSafe<SocketStream>; ~SocketStream(); - // Finish the job. Once finished, calls OnClose of delegate, and no more + // Finishes the job. + // Calls OnError and OnClose of delegate, and no more // notifications will be sent to delegate. - void Finish(); + void Finish(int result); - void DidEstablishConnection(); + int DidEstablishConnection(); void DidReceiveData(int result); void DidSendData(int result); @@ -196,7 +204,7 @@ class SocketStream : public base::RefCountedThreadSafe<SocketStream> { void OnReadCompleted(int result); void OnWriteCompleted(int result); - int DoLoop(int result); + void DoLoop(int result); int DoResolveProxy(); int DoResolveProxyComplete(int result); |