summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/socket_stream/socket_stream.cc79
-rw-r--r--net/socket_stream/socket_stream.h18
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);