diff options
-rw-r--r-- | net/base/nss_memio.c | 11 | ||||
-rw-r--r-- | net/base/nss_memio.h | 7 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_nss.cc | 11 |
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; |