On 11/2/06, Rob Crittenden <[EMAIL PROTECTED]> wrote:
Nelson B wrote:
> 1. Is this a blocking socket, or non-blocking?

non-blocking, not my choice.

Interesting issue.

> 2. If non-blocking, are you certain that the connection has completed?
>    That is, are you certain that the TCP's "three phase connect" is
>    completely done?  This is tricky for non-blocking sockets, and trivial
>    for blocking sockets.

I'm not sure it has completed, hence the simplistic loop and my plea for
assistance. Despite empirical evidence that it "worked" in my 3 test
cases this code is obviously bogus.

The best way that I know of to check for this is to select against the
descriptor for writing with a timeout of 0.  Once it returns "able to
be written without blocking" its 3-phase handshake is complete.  (I'm
not sure of select()'s behavior for reading against a socket that has
0 bytes to read.)

> 3. Is this the first handshake on the socket after the connect? or
>    Is it a subsequent (e.g. second) handshake on the socket?

First connection only.

> 4. Is this a "server speaks first" application protocol? or
>    is this a "client speaks first" protocol?

Client speaks first, HTTPS.

Does the client need to authenticate itself to the server before the
server will authenticate itself to the client?

If so, you could reverse the roles -- the TCP connector would call the
server methods, and the TCP listener would call the client methods.

> 5. What if some other error occurs besides PR_END_OF_FILE_ERROR?
>    This loop continues.  IMO, it should not.  Some errors leave the
>    SSL socket in a state where it cannot continue.  This includes
>    PR_IO_TIMEOUT_ERROR, if I'm not mistaken.
>
>    If you ignore the error code and call an I/O function on the SSL socket
>    again, it will return an error again immediately.  As coded, this will
>    be an infinite loop.

Question (for Nelson): is there a macro to test an error code to see
if it's fatal?  (since EWOULDBLOCK is a nonfatal error...)

> 6. IMO, you need to check every SSL call (and that includes PR_Recv)
>    to see if it succeeded or failed, and not continue to use the socket
>    on failure.  PR_WOULD_BLOCK_ERROR (a.k.a. EWOULDBLOCK) is obviously
>    an exception to this rule, but needs to be handled with PR_Poll.

Yes, you're right, I was being lazy, but in this case it will ALWAYS
fail since there should never be any data to peek at since this is the
first (and only) connection. But I suppose I should consider the case
where the remote closes he connection as well, see above for that fix.

You need to handle: remote refuses connection, remote half-accepts and
then times out, remote accepts and then closes, remote sends
unexpected RST, remote accepts and then times out.  A write to any of
these will end up raising a SIGPIPE unless you've told it not to.

> 7. Why are you using such a short timeout on PR_Recv?

So it doesn't cause a noticable pause in the connection. There will
never be any "data" to peek at so I am guaranteed to wait a certain
number of PRIntervals until PR_Recv returns. A larger value will almost
certainly negate the need for the icky loop but even if the handshake is
done, it'll hang around waiting for the timeout to end.

Hmm.  You might also try doing a select() on the file descriptor at
that point for reading, and then once there's data there deal with it.

>> My questions are:
>>
>> 1. Do I need the loop or will the PR_Recv, even with such a short
>> timeout, do the trick for me?
>
> What trick are you trying to do?

Force a handshake to complete on a non-blocking socket without doing I/O
with PR_Send/Write or PR_Read/Recv (in non-peek).

PR_Recv (in peek) should cause the handshake to start, if I understand
correctly.

> In this case, you're the client and you're waiting for the server to say
> something (apparently a "server speaks first" protocol, such as SMTP).
> Assuming your socket is blocking, PR_Recv by itself should do the job for
> you without a loop, and with a reasonable timeout.

Ah, I see. I sort of threw that in as a Hail Mary to no effect. This is
one of those side projects that you work on despite having a million
other, more important things to do. I didn't really spend a lot of time
on it and when I was done, saw that it wasn't my best work. But still, I
thought this was an interesting problem so thought I would try to fix it.

It would be a whole lot simpler if I didn't want to force the handshake.
Indeed, that is how I initially wrote it, but then I changed my mind and
wrenched the code until it "worked" the way I wanted.

The problem being, at a baser level, that there doesn't appear to be a
way to send a client_hello message without receiving a server_hello
first?

-Kyle H
_______________________________________________
dev-tech-crypto mailing list
dev-tech-crypto@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-tech-crypto

Reply via email to