I have a blocking SSL BIO object which I want to send data to. The problem is that the connection was closed on the remote side and I cannot find that out until I do a read (BIO_write does NOT return an error). However, I cannot read before I send since I do not want to block. Lastly, the code responsible for sending the data and the code responsible for reading are separate meaning that the failed read cannot trigger another send. How do I fix this?
Share
There are two kinds of “close” states, and are referred to as “half-close” states. They mostly have to do with whether one side or the other side of a socket is going to be sending any more application data. When your
recvcall returns 0, it is actually notifying you that there is no more data to be received. However, it is still okay to send data, unless thesendcall signals some other kind of error, likeEPIPEorECONNRESET(I am not sure what the windows equivalents of these are for winsock, but I know they are there). IfSSL_writeis not returning an error, it is because the other side of the socket is still accepting the data.The
recvcall allows a non-blocking check for the “no more data” state, and it can be done like this:If
ris0, the socket has receved an indication that there is no more data pending from the other end. Otherwise, the call will return1for a byte of data (which is still in the input buffer because ofMSG_PEEK), or-1. If theerrnoisEAGAIN(which is possible because ofMSG_DONTWAIT) there is no error. Any othererrnovalue should be consulted, but is likely an indication that the socket is in an invalid state, and needs to be closed.Before the socket gets closed, the OpenSSL application is supposed to make sure
SSL_shutdownhas returned 1. Then, thecloseon the socket occurs after theSSLobject gets destroyed (withSSL_free). What this means is that, unless the application does something abnormal, both sides of the socket using OpenSSL should have seenSSL_shutdownreturn1and then both sides can safely close the connection.If you want to check for the shutdown state of your
SSLcontext, you can useSSL_get_shutdown, which will report whether or not the other end has started theSSL_shutdownsequence.