Nelson B Bolyard wrote:
On 2009-06-19 12:48 PDT, Rich Megginson wrote:
Does NSS support non-blocking sockets?
Yes.
I'm running into a problem while using NSS with non-blocking sockets. I
have my own PR_Recv function that does something like this:
Although you called it a "PR_Recv" function, I gather that it is actually
an NSPR IO layer's recv method (a method in the layer's PRIOMethods struct).
I will assume that is correct.
Yes. This is an implementation of a PRIOMethods stack. So what I mean
is "this is the function that implements the PR_Recv functionality for
this layer".
static int PR_CALLBACK
my_PR_Recv(PRFileDesc *fd, void *buf, PRInt32 len, PRIntn flags,
PRIntervalTime timeout)
{
...
rc = my_real_read_function( realfd, buf, len );
if (rc <= 0) {
if ( errno == EAGAIN || errno == EWOULDBLOCK ) {
PR_SetError( PR_WOULD_BLOCK_ERROR, errno );
}
}
return rc;
}
In the particular stack trace I'm looking at, this is called via
ssl_DefRecv
ssl3_GatherData
ssl3_GatherCompleteHandshake
ssl_GatherRecord1stHandshake
I'm guessing the rest of the stack resembles this
ssl_Do1stHandshake
ssl_SecureRecv
PR_Recv
No.
ssl_Do1stHandshake
SSL_ForceHandshake
my_accept
This is a server accepting an SSL connection.
I think the problem is that ssl3_GatherData does not check for WOULD_BLOCK:
Before we look at potential causes of the problem, I think we need a
description of the problem.
Ok. The problem is that, in the above code, realfd is set to
non-blocking, and my_real_read_function is returning rc == -1 with errno
set to EAGAIN. This means that the read operation would block. If I
simply set the error to PR_WOULD_BLOCK_ERROR and pass the error
condition back up through the SSL layer, SSL interprets this as a hard
error - FAIL.
This is the problem here. I think it should check to see if
ssl_SocketIsBlocking(), then check to see if the error is WOULD_BLOCK,
then return rv = SECWouldBlock
Why do you think that?
SECWouldBlock doesn't mean "underlying socket would block".
Ok.
Because when it returns rv = SECFailure, this goes up to the caller,
ssl3_GatherCompleteHandshake, which just returns it:
Correct. It should be returned all the way out to the caller of PR_Recv.
So then to SSL_ForceHandshake and my_accept() function.
ssl_GatherRecord1stHandshake gets rv SECFailure instead of SECWouldBlock.
Correct.
It looks as though it can properly handle SECWouldBlock, but
ssl3_GatherData -> ssl3_GatherCompleteHandshake do not return that rv in
this case.
Correct. PRIOMethods functions do not return SECStatus values.
SECWouldBlock is not a valid return value from any NSPR function.
Ok.
Moreover, inside of libSSL, SECWouldBlock does not mean exactly the same
thing as PR_FAILURE with error code PR_WOULD_BLOCK_ERROR. Inside of
libSSL, SECWouldBlock means that progress on this SSL socket is blocked
by something OTHER THAN blockage of the underlying socket on network IO
activity, such as waiting for a browser user to dismiss a dialog, or
waiting for some activity to complete on ANOTHER socket, such as when
fetching OCSP responses.
Ok.
Note that even if my PR_Recv function returned 0 here, the NSS code
would interpret that as a closed socket:
Not closed, but at EOF. Yes, that's exactly as expected.
Is NSS supposed to support non-blocking sockets?
Yes.
If so, what am I doing wrong?
Since you haven't told us what the problem is, what its symptoms are,
I can only guess. I would guess that the problem is in the caller of
PR_Recv. I would guess that it is expecting to get back SECWouldBlock
from PR_Recv, and when it gets PR_FAILURE, it doesn't check the error
code for PR_WOULD_BLOCK_ERROR, and then call PR_Poll to wait for IO
completion. Or, maybe, it calls PR_Poll, but gets the "wrong answer"
due to a problem in some IO layer's poll method.
The problem is that my read_function(realfd) is returning EAGAIN, and I
need to somehow propagate that back up to the SSL layer (via setting the
pr error to PR_WOULD_BLOCK_ERROR) to tell the SSL layer that data is not
yet available.
Or, my_PR_Recv function needs to do a poll() to wait until all of the
requested data has been read, and not return until that happens, or some
real error condition has occurred.
--
dev-tech-crypto mailing list
dev-tech-crypto@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-tech-crypto