Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2001)

Unified Diff: net/socket/ssl_client_socket_mac.cc

Issue 266078: Make SSLClientSocketMac full-duplex (Closed)
Patch Set: cleanup OnTransportWriteComplete Created 11 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/socket/ssl_client_socket_mac.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/socket/ssl_client_socket_mac.cc
diff --git a/net/socket/ssl_client_socket_mac.cc b/net/socket/ssl_client_socket_mac.cc
index 9eef7273a349259eb824aaa02398e6ef52e01a29..60561045a282aaf40213c8f496233e510622db3c 100644
--- a/net/socket/ssl_client_socket_mac.cc
+++ b/net/socket/ssl_client_socket_mac.cc
@@ -68,12 +68,12 @@
// So, like in any good relationship, we're forced to lie. Whenever Secure
// Transport asks for data to be written, we take it all and lie about it always
// being written. We spin in a loop (see SSLWriteCallback() and
-// OnWriteComplete()) independent of the main state machine writing the data to
-// the network, and get the data out. The main consequence of this independence
-// from the state machine is that we require a full-duplex transport underneath
-// us since we can't use it to keep our reading and writing
-// straight. Fortunately, the NSS implementation also has this issue to deal
-// with, so we share the same Libevent-based full-duplex TCP socket.
+// OnTransportWriteComplete()) independent of the main state machine writing
+// the data to he network, and get the data out. The main consequence of this
+// independence from the state machine is that we require a full-duplex
+// transport underneath us since we can't use it to keep our reading and
+// writing straight. Fortunately, the NSS implementation also has this issue
+// to deal with, so we share the same Libevent-based full-duplex TCP socket.
//
// A side comment on return values might be in order. Those who haven't taken
// the time to read the documentation (ahem, header comments) in our various
@@ -297,14 +297,20 @@ X509Certificate* GetServerCert(SSLContextRef ssl_context) {
SSLClientSocketMac::SSLClientSocketMac(ClientSocket* transport_socket,
const std::string& hostname,
const SSLConfig& ssl_config)
- : io_callback_(this, &SSLClientSocketMac::OnIOComplete),
- write_callback_(this, &SSLClientSocketMac::OnWriteComplete),
+ : handshake_io_callback_(this, &SSLClientSocketMac::OnHandshakeIOComplete),
+ transport_read_callback_(this,
+ &SSLClientSocketMac::OnTransportReadComplete),
+ transport_write_callback_(this,
+ &SSLClientSocketMac::OnTransportWriteComplete),
transport_(transport_socket),
hostname_(hostname),
ssl_config_(ssl_config),
- user_callback_(NULL),
- next_state_(STATE_NONE),
- next_io_state_(STATE_NONE),
+ user_connect_callback_(NULL),
+ user_read_callback_(NULL),
+ user_write_callback_(NULL),
+ user_read_buf_len_(0),
+ user_write_buf_len_(0),
+ next_handshake_state_(STATE_NONE),
completed_handshake_(false),
handshake_interrupted_(false),
ssl_context_(NULL),
@@ -319,8 +325,8 @@ SSLClientSocketMac::~SSLClientSocketMac() {
int SSLClientSocketMac::Connect(CompletionCallback* callback) {
DCHECK(transport_.get());
- DCHECK(next_state_ == STATE_NONE);
- DCHECK(!user_callback_);
+ DCHECK(next_handshake_state_ == STATE_NONE);
+ DCHECK(!user_connect_callback_);
OSStatus status = noErr;
@@ -415,10 +421,10 @@ int SSLClientSocketMac::Connect(CompletionCallback* callback) {
}
}
- next_state_ = STATE_HANDSHAKE_START;
- int rv = DoLoop(OK);
+ next_handshake_state_ = STATE_HANDSHAKE_START;
+ int rv = DoHandshakeLoop(OK);
if (rv == ERR_IO_PENDING)
- user_callback_ = callback;
+ user_connect_callback_ = callback;
return rv;
}
@@ -460,19 +466,18 @@ bool SSLClientSocketMac::IsConnectedAndIdle() const {
int SSLClientSocketMac::Read(IOBuffer* buf, int buf_len,
CompletionCallback* callback) {
DCHECK(completed_handshake_);
- DCHECK(next_state_ == STATE_NONE);
- DCHECK(!user_callback_);
- DCHECK(!user_buf_);
+ DCHECK(!user_read_callback_);
+ DCHECK(!user_read_buf_);
- user_buf_ = buf;
- user_buf_len_ = buf_len;
+ user_read_buf_ = buf;
+ user_read_buf_len_ = buf_len;
- next_state_ = STATE_PAYLOAD_READ;
- int rv = DoLoop(OK);
+ int rv = DoPayloadRead();
if (rv == ERR_IO_PENDING) {
- user_callback_ = callback;
+ user_read_callback_ = callback;
} else {
- user_buf_ = NULL;
+ user_read_buf_ = NULL;
+ user_read_buf_len_ = 0;
}
return rv;
}
@@ -480,19 +485,18 @@ int SSLClientSocketMac::Read(IOBuffer* buf, int buf_len,
int SSLClientSocketMac::Write(IOBuffer* buf, int buf_len,
CompletionCallback* callback) {
DCHECK(completed_handshake_);
- DCHECK(next_state_ == STATE_NONE);
- DCHECK(!user_callback_);
- DCHECK(!user_buf_);
+ DCHECK(!user_write_callback_);
+ DCHECK(!user_write_buf_);
- user_buf_ = buf;
- user_buf_len_ = buf_len;
+ user_write_buf_ = buf;
+ user_write_buf_len_ = buf_len;
- next_state_ = STATE_PAYLOAD_WRITE;
- int rv = DoLoop(OK);
+ int rv = DoPayloadWrite();
if (rv == ERR_IO_PENDING) {
- user_callback_ = callback;
+ user_write_callback_ = callback;
} else {
- user_buf_ = NULL;
+ user_write_buf_ = NULL;
+ user_write_buf_len_ = 0;
}
return rv;
}
@@ -528,40 +532,97 @@ void SSLClientSocketMac::GetSSLCertRequestInfo(
// TODO(wtc): implement this.
}
-void SSLClientSocketMac::DoCallback(int rv) {
+void SSLClientSocketMac::DoConnectCallback(int rv) {
DCHECK(rv != ERR_IO_PENDING);
- DCHECK(user_callback_);
+ DCHECK(user_connect_callback_);
+ DCHECK(next_handshake_state_ == STATE_NONE);
- // since Run may result in Read being called, clear user_callback_ up front.
- CompletionCallback* c = user_callback_;
- user_callback_ = NULL;
- user_buf_ = NULL;
+ CompletionCallback* c = user_connect_callback_;
+ user_connect_callback_ = NULL;
+ c->Run(rv > OK ? OK : rv);
+}
+
+void SSLClientSocketMac::DoReadCallback(int rv) {
+ DCHECK(rv != ERR_IO_PENDING);
+ DCHECK(user_read_callback_);
+
+ // Since Run may result in Read being called, clear user_read_callback_ up
+ // front.
+ CompletionCallback* c = user_read_callback_;
+ user_read_callback_ = NULL;
+ user_read_buf_ = NULL;
+ user_read_buf_len_ = 0;
+ c->Run(rv);
+}
+
+void SSLClientSocketMac::DoWriteCallback(int rv) {
+ DCHECK(rv != ERR_IO_PENDING);
+ DCHECK(user_write_callback_);
+
+ // Since Run may result in Write being called, clear user_write_callback_ up
+ // front.
+ CompletionCallback* c = user_write_callback_;
+ user_write_callback_ = NULL;
+ user_write_buf_ = NULL;
+ user_write_buf_len_ = 0;
c->Run(rv);
}
-void SSLClientSocketMac::OnIOComplete(int result) {
- if (next_io_state_ != STATE_NONE) {
- State next_state = next_state_;
- next_state_ = next_io_state_;
- next_io_state_ = STATE_NONE;
- result = DoLoop(result);
- next_state_ = next_state;
+void SSLClientSocketMac::OnHandshakeIOComplete(int result) {
+ DCHECK(next_handshake_state_ != STATE_NONE);
+ int rv = DoHandshakeLoop(result);
+ if (rv != ERR_IO_PENDING)
+ DoConnectCallback(rv);
+}
+
+void SSLClientSocketMac::OnTransportReadComplete(int result) {
+ if (result > 0) {
+ char* buffer =
+ &recv_buffer_[recv_buffer_.size() - recv_buffer_tail_slop_];
+ memcpy(buffer, read_io_buf_->data(), result);
+ recv_buffer_tail_slop_ -= result;
+ }
+ read_io_buf_ = NULL;
+
+ if (next_handshake_state_ != STATE_NONE) {
+ int rv = DoHandshakeLoop(result);
+ if (rv != ERR_IO_PENDING)
+ DoConnectCallback(rv);
+ return;
}
- if (next_state_ != STATE_NONE) {
- int rv = DoLoop(result);
+ if (user_read_buf_) {
+ if (result < 0) {
+ DoReadCallback(result);
+ return;
+ }
+ int rv = DoPayloadRead();
if (rv != ERR_IO_PENDING)
- DoCallback(rv);
+ DoReadCallback(rv);
+ }
+}
+
+void SSLClientSocketMac::OnTransportWriteComplete(int result) {
+ if (result < 0) {
+ pending_send_error_ = result;
+ return;
}
+ send_buffer_.erase(send_buffer_.begin(),
+ send_buffer_.begin() + result);
+ if (!send_buffer_.empty())
+ SSLWriteCallback(this, NULL, NULL);
+
+ // Since SSLWriteCallback() lies to return noErr even if transport_->Write()
+ // returns ERR_IO_PENDING, we don't need to any callbacks here.
wtc 2009/10/22 22:06:44 Nit: add "call" or "do" after "need to".
}
// This is the main loop driving the state machine. Most calls coming from the
// outside just set up a few variables and jump into here.
-int SSLClientSocketMac::DoLoop(int last_io_result) {
- DCHECK(next_state_ != STATE_NONE);
+int SSLClientSocketMac::DoHandshakeLoop(int last_io_result) {
+ DCHECK(next_handshake_state_ != STATE_NONE);
int rv = last_io_result;
do {
- State state = next_state_;
- next_state_ = STATE_NONE;
+ State state = next_handshake_state_;
+ next_handshake_state_ = STATE_NONE;
switch (state) {
case STATE_HANDSHAKE_START:
// Do the SSL/TLS handshake, up to the server certificate message.
@@ -579,32 +640,19 @@ int SSLClientSocketMac::DoLoop(int last_io_result) {
// Do the SSL/TLS handshake, after the server certificate message.
rv = DoHandshakeFinish();
break;
- case STATE_READ_COMPLETE:
- // A read off the network is complete; do the paperwork.
- rv = DoReadComplete(rv);
- break;
- case STATE_PAYLOAD_READ:
- // Do a read of data from the network.
- rv = DoPayloadRead();
- break;
- case STATE_PAYLOAD_WRITE:
- // Do a write of data to the network.
- rv = DoPayloadWrite();
- break;
default:
rv = ERR_UNEXPECTED;
NOTREACHED() << "unexpected state";
break;
}
- } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
+ } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
return rv;
}
int SSLClientSocketMac::DoHandshakeStart() {
OSStatus status = SSLHandshake(ssl_context_);
-
if (status == errSSLWouldBlock)
- next_state_ = STATE_HANDSHAKE_START;
+ next_handshake_state_ = STATE_HANDSHAKE_START;
server_cert_ = GetServerCert(ssl_context_);
@@ -616,7 +664,7 @@ int SSLClientSocketMac::DoHandshakeStart() {
// so that we have the certificate status (valid, expired but overridden
// by the user, EV, etc.) available. Eliminate this step once we have
// a certificate validation result cache.
- next_state_ = STATE_VERIFY_CERT;
+ next_handshake_state_ = STATE_VERIFY_CERT;
if (status == errSSLServerAuthCompletedFlag) {
// Override errSSLServerAuthCompletedFlag as it's not actually an error,
// but rather an indication that we're only half way through the
@@ -630,7 +678,7 @@ int SSLClientSocketMac::DoHandshakeStart() {
}
int SSLClientSocketMac::DoVerifyCert() {
- next_state_ = STATE_VERIFY_CERT_COMPLETE;
+ next_handshake_state_ = STATE_VERIFY_CERT_COMPLETE;
if (!server_cert_)
return ERR_UNEXPECTED;
@@ -642,7 +690,8 @@ int SSLClientSocketMac::DoVerifyCert() {
flags |= X509Certificate::VERIFY_EV_CERT;
verifier_.reset(new CertVerifier);
return verifier_->Verify(server_cert_, hostname_, flags,
- &server_cert_verify_result_, &io_callback_);
+ &server_cert_verify_result_,
+ &handshake_io_callback_);
}
int SSLClientSocketMac::DoVerifyCertComplete(int result) {
@@ -657,12 +706,12 @@ int SSLClientSocketMac::DoVerifyCertComplete(int result) {
// in a non-resumed session) occurs in two steps. Continue on to the second
// step if the certificate is OK.
if (result == OK)
- next_state_ = STATE_HANDSHAKE_FINISH;
+ next_handshake_state_ = STATE_HANDSHAKE_FINISH;
} else {
// If the session was resumed or session resumption was disabled, we're
// done with the handshake.
completed_handshake_ = true;
- DCHECK(next_state_ == STATE_NONE);
+ DCHECK(next_handshake_state_ == STATE_NONE);
}
return result;
@@ -672,47 +721,21 @@ int SSLClientSocketMac::DoHandshakeFinish() {
OSStatus status = SSLHandshake(ssl_context_);
if (status == errSSLWouldBlock)
- next_state_ = STATE_HANDSHAKE_FINISH;
+ next_handshake_state_ = STATE_HANDSHAKE_FINISH;
- if (status == noErr)
+ if (status == noErr) {
completed_handshake_ = true;
-
- return NetErrorFromOSStatus(status);
-}
-
-int SSLClientSocketMac::DoReadComplete(int result) {
- if (result < 0) {
- read_io_buf_ = NULL;
- return result;
+ DCHECK(next_handshake_state_ == STATE_NONE);
}
- char* buffer = &recv_buffer_[recv_buffer_.size() - recv_buffer_tail_slop_];
- memcpy(buffer, read_io_buf_->data(), result);
- read_io_buf_ = NULL;
-
- recv_buffer_tail_slop_ -= result;
-
- return result;
-}
-
-void SSLClientSocketMac::OnWriteComplete(int result) {
- if (result < 0) {
- pending_send_error_ = result;
- return;
- }
-
- send_buffer_.erase(send_buffer_.begin(),
- send_buffer_.begin() + result);
-
- if (!send_buffer_.empty())
- SSLWriteCallback(this, NULL, NULL);
+ return NetErrorFromOSStatus(status);
}
int SSLClientSocketMac::DoPayloadRead() {
size_t processed = 0;
OSStatus status = SSLRead(ssl_context_,
- user_buf_->data(),
- user_buf_len_,
+ user_read_buf_->data(),
+ user_read_buf_len_,
&processed);
// There's a subtle difference here in semantics of the "would block" errors.
@@ -731,17 +754,14 @@ int SSLClientSocketMac::DoPayloadRead() {
return OK;
}
- if (status == errSSLWouldBlock)
- next_state_ = STATE_PAYLOAD_READ;
-
return NetErrorFromOSStatus(status);
}
int SSLClientSocketMac::DoPayloadWrite() {
size_t processed = 0;
OSStatus status = SSLWrite(ssl_context_,
- user_buf_->data(),
- user_buf_len_,
+ user_write_buf_->data(),
+ user_write_buf_len_,
&processed);
if (processed > 0)
@@ -783,8 +803,8 @@ int SSLClientSocketMac::DoPayloadWrite() {
// When executing a read, we pass a pointer to the beginning of the tail slop
// area (guaranteed to be contiguous space because it's a vector, unlike, say, a
// deque (sigh)) and the size of the tail slop. When we get data (either here in
-// SSLReadCallback() or above in DoReadComplete()) we subtract the number of
-// bytes received from the tail slop value. That moves those bytes
+// SSLReadCallback() or above in OnTransportReadComplete()) we subtract the
+// number of bytes received from the tail slop value. That moves those bytes
// (conceptually, not physically) from the tail slop area to the area containing
// real data.
//
@@ -834,7 +854,7 @@ OSStatus SSLClientSocketMac::SSLReadCallback(SSLConnectionRef connection,
// If we have I/O in flight, promise we'll get back to them and use the
// existing callback to do so
- if (us->next_io_state_ == STATE_READ_COMPLETE) {
+ if (us->read_io_buf_) {
*data_length = 0;
return errSSLWouldBlock;
}
@@ -857,7 +877,7 @@ OSStatus SSLClientSocketMac::SSLReadCallback(SSLConnectionRef connection,
us->read_io_buf_ = new IOBuffer(*data_length - total_read);
rv = us->transport_->Read(us->read_io_buf_,
*data_length - total_read,
- &us->io_callback_);
+ &us->transport_read_callback_);
if (rv >= 0) {
memcpy(buffer, us->read_io_buf_->data(), rv);
@@ -883,11 +903,8 @@ OSStatus SSLClientSocketMac::SSLReadCallback(SSLConnectionRef connection,
}
}
- if (rv == ERR_IO_PENDING) {
- us->next_io_state_ = STATE_READ_COMPLETE;
- } else {
+ if (rv != ERR_IO_PENDING)
us->read_io_buf_ = NULL;
- }
if (rv < 0)
return OSStatusFromNetError(rv);
@@ -932,7 +949,7 @@ OSStatus SSLClientSocketMac::SSLWriteCallback(SSLConnectionRef connection,
memcpy(buffer->data(), &us->send_buffer_[0], us->send_buffer_.size());
rv = us->transport_->Write(buffer,
us->send_buffer_.size(),
- &us->write_callback_);
+ &us->transport_write_callback_);
if (rv > 0) {
us->send_buffer_.erase(us->send_buffer_.begin(),
us->send_buffer_.begin() + rv);
« no previous file with comments | « net/socket/ssl_client_socket_mac.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698