summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/base/nss_memio.c11
-rw-r--r--net/base/nss_memio.h7
-rw-r--r--net/socket/ssl_client_socket_nss.cc11
3 files changed, 29 insertions, 0 deletions
diff --git a/net/base/nss_memio.c b/net/base/nss_memio.c
index c1a89c3..4092c17 100644
--- a/net/base/nss_memio.c
+++ b/net/base/nss_memio.c
@@ -55,6 +55,10 @@ struct PRFilePrivate {
/* if set, empty I/O returns EOF instead of EWOULDBLOCK */
int eof;
+
+ /* if set, the number of bytes requested from readbuf that were not
+ * fulfilled (due to readbuf being empty) */
+ int read_requested;
};
/*--------------- private memio_buffer functions ---------------------*/
@@ -223,6 +227,7 @@ static int PR_CALLBACK memio_Recv(PRFileDesc *fd, void *buf, PRInt32 len,
PR_ASSERT(mb->bufsize);
rv = memio_buffer_get(mb, buf, len);
if (rv == 0 && !secret->eof) {
+ secret->read_requested = len;
if (mb->last_err)
PR_SetError(mb->last_err, 0);
else
@@ -230,6 +235,7 @@ static int PR_CALLBACK memio_Recv(PRFileDesc *fd, void *buf, PRInt32 len,
return -1;
}
+ secret->read_requested = 0;
return rv;
}
@@ -382,6 +388,11 @@ memio_Private *memio_GetSecret(PRFileDesc *fd)
return (memio_Private *)secret;
}
+int memio_GetReadRequest(memio_Private *secret)
+{
+ return ((PRFilePrivate *)secret)->read_requested;
+}
+
int memio_GetReadParams(memio_Private *secret, char **buf)
{
struct memio_buffer* mb = &((PRFilePrivate *)secret)->readbuf;
diff --git a/net/base/nss_memio.h b/net/base/nss_memio.h
index 7d889eb..a8bbc2c 100644
--- a/net/base/nss_memio.h
+++ b/net/base/nss_memio.h
@@ -50,6 +50,13 @@ void memio_SetPeerName(PRFileDesc *fd, const PRNetAddr *peername);
*/
memio_Private *memio_GetSecret(PRFileDesc *fd);
+/* Ask memio how many bytes were requested by a higher layer if the
+ * last attempt to read data resulted in PR_WOULD_BLOCK_ERROR, due to the
+ * transport buffer being empty. If the last attempt to read data from the
+ * memio did not result in PR_WOULD_BLOCK_ERROR, returns 0.
+ */
+int memio_GetReadRequest(memio_Private *secret);
+
/* Ask memio where to put bytes from the network, and how many it can handle.
* Returns bytes available to write, or 0 if none available.
* Puts current buffer position into *buf.
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index f75b5f8..92f6c37 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -2101,6 +2101,17 @@ int SSLClientSocketNSS::Core::BufferRecv() {
if (transport_recv_busy_)
return ERR_IO_PENDING;
+ // If NSS is blocked on reading from |nss_bufs_|, because it is empty,
+ // determine how much data NSS wants to read. If NSS was not blocked,
+ // this will return 0.
+ int requested = memio_GetReadRequest(nss_bufs_);
+ if (requested == 0) {
+ // This is not a perfect match of error codes, as no operation is
+ // actually pending. However, returning 0 would be interpreted as a
+ // possible sign of EOF, which is also an inappropriate match.
+ return ERR_IO_PENDING;
+ }
+
char* buf;
int nb = memio_GetReadParams(nss_bufs_, &buf);
int rv;