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

Unified Diff: net/socket/ssl_client_socket_nss.cc

Issue 11366155: SSLClientSocket::IsConnected should care for internal buffers (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: rebase to new rev. Created 7 years, 11 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/data/websocket/split_frame_check.html ('k') | net/socket/ssl_client_socket_win.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/socket/ssl_client_socket_nss.cc
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index 92f6c37f4ef564aeb959f6e16ef969674a432b63..ccdb7084e8f00f40c6fce5b52ceacac07781e4f5 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -571,9 +571,9 @@ int MapNSSClientHandshakeError(PRErrorCode err) {
// |-------------------------------V
// BufferRecvComplete()
// |
-// PostOrRunCallback()
+// DoReadCallback()
// V-------------------------------|
-// PostOrRunCallback()
+// UpdateReadStatus()
Ryan Sleevi 2013/01/07 18:59:04 NACK on this. The intention of PostOrRunCallback i
Takashi Toyoshima 2013/01/08 06:25:39 Oh, I miss the case of single-threaded model and m
// V---------------------|
// (Read Callback)
//
@@ -637,6 +637,10 @@ class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> {
int Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback);
int Write(IOBuffer* buf, int buf_len, const CompletionCallback& callback);
+ // Called on the network task runner.
+ bool HasPendingAsyncOperation();
+ bool HasUnhandledData();
+
private:
friend class base::RefCountedThreadSafe<Core>;
~Core();
@@ -735,6 +739,10 @@ class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> {
void DoConnectCallback(int result);
void DoReadCallback(int result);
void DoWriteCallback(int result);
+ void UpdateNSSStatus(int amount_in_read_buffer,
+ bool operation_is_read,
+ const CompletionCallback& callback,
+ int rv);
// Client channel ID handler.
static SECStatus ClientChannelIDHandler(
@@ -812,6 +820,11 @@ class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> {
ServerBoundCertService* server_bound_cert_service_;
ServerBoundCertService::RequestHandle domain_bound_cert_request_handle_;
+ // The information about NSS task runner status.
+ int unhandled_buffer_size_;
+ bool waiting_read_;
+ bool waiting_write_;
+
////////////////////////////////////////////////////////////////////////////
// Members that are ONLY accessed on the NSS task runner:
////////////////////////////////////////////////////////////////////////////
@@ -892,6 +905,9 @@ SSLClientSocketNSS::Core::Core(
weak_net_log_factory_(net_log),
server_bound_cert_service_(server_bound_cert_service),
domain_bound_cert_request_handle_(NULL),
+ unhandled_buffer_size_(0),
+ waiting_read_(false),
+ waiting_write_(false),
host_and_port_(host_and_port),
ssl_config_(ssl_config),
nss_fd_(NULL),
@@ -1104,9 +1120,11 @@ int SSLClientSocketNSS::Core::Read(IOBuffer* buf, int buf_len,
DCHECK(user_connect_callback_.is_null());
DCHECK(!user_read_buf_);
DCHECK(nss_bufs_);
+ DCHECK(!waiting_read_);
user_read_buf_ = buf;
user_read_buf_len_ = buf_len;
+ waiting_read_ = true;
int rv = DoReadLoop(OK);
if (rv == ERR_IO_PENDING) {
@@ -1114,6 +1132,7 @@ int SSLClientSocketNSS::Core::Read(IOBuffer* buf, int buf_len,
} else {
user_read_buf_ = NULL;
user_read_buf_len_ = 0;
+ waiting_read_ = false;
if (!OnNetworkTaskRunner()) {
PostOrRunCallback(FROM_HERE, base::Bind(callback, rv));
@@ -1146,9 +1165,11 @@ int SSLClientSocketNSS::Core::Write(IOBuffer* buf, int buf_len,
DCHECK(user_connect_callback_.is_null());
DCHECK(!user_write_buf_);
DCHECK(nss_bufs_);
+ DCHECK(!waiting_write_);
user_write_buf_ = buf;
user_write_buf_len_ = buf_len;
+ waiting_write_ = true;
int rv = DoWriteLoop(OK);
if (rv == ERR_IO_PENDING) {
@@ -1156,6 +1177,7 @@ int SSLClientSocketNSS::Core::Write(IOBuffer* buf, int buf_len,
} else {
user_write_buf_ = NULL;
user_write_buf_len_ = 0;
+ waiting_write_ = false;
if (!OnNetworkTaskRunner()) {
PostOrRunCallback(FROM_HERE, base::Bind(callback, rv));
@@ -1166,6 +1188,16 @@ int SSLClientSocketNSS::Core::Write(IOBuffer* buf, int buf_len,
return rv;
}
+bool SSLClientSocketNSS::Core::HasPendingAsyncOperation() {
+ DCHECK(OnNetworkTaskRunner());
+ return waiting_read_ || waiting_write_;
+}
+
+bool SSLClientSocketNSS::Core::HasUnhandledData() {
+ DCHECK(OnNetworkTaskRunner());
+ return unhandled_buffer_size_ != 0;
+}
+
bool SSLClientSocketNSS::Core::OnNSSTaskRunner() const {
return nss_task_runner_->RunsTasksOnCurrentThread();
}
@@ -2257,10 +2289,19 @@ void SSLClientSocketNSS::Core::DoReadCallback(int rv) {
user_read_buf_ = NULL;
user_read_buf_len_ = 0;
- base::Closure c = base::Bind(
- base::ResetAndReturn(&user_read_callback_),
- rv);
- PostOrRunCallback(FROM_HERE, c);
+ char* buf;
+ int amount_in_read_buffer = memio_GetReadParams(nss_bufs_, &buf);
+ CompletionCallback cb = base::ResetAndReturn(&user_read_callback_);
+ // Curry the |amount_int_read_buffer| and |cb| back to the network task
+ // runner.
+ network_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&Core::UpdateNSSStatus,
+ this,
+ amount_in_read_buffer,
+ true, // Operation is read.
+ cb,
+ rv));
Ryan Sleevi 2013/01/07 18:59:04 NACK: See above comments re: PostOrRunCallback. Yo
Takashi Toyoshima 2013/01/08 06:25:39 Done.
}
void SSLClientSocketNSS::Core::DoWriteCallback(int rv) {
@@ -2272,10 +2313,39 @@ void SSLClientSocketNSS::Core::DoWriteCallback(int rv) {
// up front.
user_write_buf_ = NULL;
user_write_buf_len_ = 0;
- base::Closure c = base::Bind(
- base::ResetAndReturn(&user_write_callback_),
- rv);
- PostOrRunCallback(FROM_HERE, c);
+ char* buf;
+ // Update buffer status because DoWriteLoop called DoTransportIO which may
+ // perform read operations.
+ int amount_in_read_buffer = memio_GetReadParams(nss_bufs_, &buf);
+ CompletionCallback cb = base::ResetAndReturn(&user_write_callback_);
+ // Curry the |cb| back to the network task runner.
+ network_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&Core::UpdateNSSStatus,
+ this,
+ amount_in_read_buffer,
+ false, // Operation is not read, but write.
+ cb,
+ rv));
Ryan Sleevi 2013/01/07 18:59:04 Also here
Takashi Toyoshima 2013/01/08 06:25:39 Done.
+}
+
+void SSLClientSocketNSS::Core::UpdateNSSStatus(
+ int amount_in_read_buffer,
+ bool operation_is_read,
+ const CompletionCallback& callback,
+ int rv) {
Ryan Sleevi 2013/01/07 18:59:04 If you're going to post a callback, you should pos
Takashi Toyoshima 2013/01/08 06:25:39 Done.
+ DCHECK(OnNetworkTaskRunner());
+ DCHECK_NE(ERR_IO_PENDING, rv);
+ DCHECK(!callback.is_null());
+ DCHECK((operation_is_read && waiting_read_) ||
+ (!operation_is_read && waiting_write_));
+
+ unhandled_buffer_size_ = amount_in_read_buffer;
+ if (operation_is_read)
+ waiting_read_ = false;
+ else
+ waiting_write_ = false;
+ PostOrRunCallback(FROM_HERE, base::Bind(callback, rv));
Ryan Sleevi 2013/01/07 18:59:04 At this point, you're guaranteed to be OnNetworkTa
Takashi Toyoshima 2013/01/08 06:25:39 Done.
}
SECStatus SSLClientSocketNSS::Core::ClientChannelIDHandler(
@@ -2898,7 +2968,17 @@ bool SSLClientSocketNSS::IsConnected() const {
// closed by the server when we send a request anyway, a false positive in
// exchange for simpler code is a good trade-off.
EnterFunction("");
- bool ret = completed_handshake_ && transport_->socket()->IsConnected();
+ bool ret;
+
+ if (!completed_handshake_)
+ ret = false;
+ else if (core_->HasPendingAsyncOperation())
+ ret = true;
+ else if (core_->HasUnhandledData())
+ ret = true;
+ else
+ ret = transport_->socket()->IsConnected();
+
LeaveFunction("");
return ret;
}
@@ -2913,7 +2993,17 @@ bool SSLClientSocketNSS::IsConnectedAndIdle() const {
// transport_->socket()->IsConnectedAndIdle() returns the desired false
// when we receive close_notify.
EnterFunction("");
- bool ret = completed_handshake_ && transport_->socket()->IsConnectedAndIdle();
+ bool ret;
+
+ if (!completed_handshake_)
+ ret = false;
+ else if (core_->HasPendingAsyncOperation())
+ ret = true; // This is probably wrong, but mirrors TCP.
+ else if (core_->HasUnhandledData())
+ ret = false;
+ else
+ ret = transport_->socket()->IsConnectedAndIdle();
+
LeaveFunction("");
return ret;
}
« no previous file with comments | « net/data/websocket/split_frame_check.html ('k') | net/socket/ssl_client_socket_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698