how to tell when no more progress can be made on an SSL connection

别说谁变了你拦得住时间么 提交于 2019-12-12 18:33:15

问题


Here

http://marc.info/?l=openssl-users&m=124386218929227

It states that

"...This is why it is very important to understand that any possible forward progress on any port (and a write operation that returns WANT_READ may have made forward progress!) requires you to retry all pending operations on all ports...."

So am I correct in understanding that an SSL_read() that returned WANT_READ may have made forward progress (even if it did not return any data)?

I have an event driven single threaded app that has 3 non blocking ssl sockets. When each socket completes its connection, I have the sockets read until I get a WANT_READ. My understanding is that a WANT_READ means I may now invoke select() and wait until the socket is ready for reading again.

When select() returns, a loop goes through the 3 sockets calling ssl_read() on each of them.

Say a read on Socket 1 returned WANT_READ and no data. Is it possible that Socket 2 returns some data, returns WANT_READ when there is nothing more to read, and has now made some progress so a read on socket 1 may now return data? But as the loop has already done the read for socket 1, it will not happen.

As the loop has run through the 3 sockets, it waits there and hangs. Could this situation happen?

If this is the case, how do I see if no more progress can be made on all 3 sockets? For example, say the loop runs through;

  • socket 1 returns WANT_READ.
  • socket 2 returns some data, then WANT_READ (and makes progress such that socket 1 can now return data)
  • socket 3 returns WANT_READ.

But based on the quote above (where any forward progress requires retrying all pending operations), I should retry all sockets again; so the second run through the loop;

  • socket 1 now returns data, then WANT_READ
  • socket 2 returns WANT_READ
  • socket 3 now returns data (because the read on socket 1 made enough progress for socket 3 to return data), then WANT_READ.

But what if the last read on socket 3 made progress so socket 2 now returns data again? So my question is (if my understanding is correct), how can I tell if no more progress can be made?

edit 1:

So what I'm seeing is this:

My loop runs through all sockets (eg say there are 2 sockets) connected to client1

  • socket 1: ssl_read() returns WANT_READ
  • socket 2: ssl_read() returns data, ssl_read() returns data again, then ssl_read() finally returns WANT_READ

Then as all sockets have returned WANT_READ, I wait on select(). However my app is still waiting for data that the client has already sent. If I get the client to start another connection (while keeping the originals active), select returns and this is what I see:

  • socket 1: ssl_read() returns data, then ssl_read() again returns WANT_READ
  • socket 2: ssl_read() returns WANT_READ
  • socket 3(new): ssl_read() returns data, then returns WANT_READ.

So select detects the new connection and runs through my loop, which goes through all active connections. This time, it has found data from socket 1 from last time, in addition to the new data on socket 3. So my theory is that select() doesn't return the first time because the data I'm waiting to receive on socket 1 has already arrived and is ready and waiting for me to call ssl_read(). But last time I called ssl_read, I got WANT_READ.


回答1:


When SSL_read() returns a negative value, you should obtain the error code from SSL_get_error(). If the error code is SSL_ERROR_WANT_READ it means that you should wait (e.g. using select() or poll) for that socket to be readable (untill some data arrives from the network). When it happens you should retry SSL_read() on that socket again. You don't have to retry SSL_read() on all SSL sockets that you have, only on those ones that returned SSL_ERROR_WANT_READ. You should do simmilar things with SSL_write() (when it returns SSL_ERROR_WANT_WRITE).

Be careful though, SSL_read() can potentially return (SSL_get_error() that is) SSL_ERROR_WANT_WRITE and SSL_write() can return SSL_ERROR_WANT_READ. It may happen, because SSL needs to send/receive some additional messages besides your data (e.g. in order to send your data it needs to send some message and receive response first).

To summarize:

  1. When n = SSL_read() returns:

    a)n > 0 --> you have just received n bytes of data

    b)n < 0 --> err = SSL_get_error() returned

    • SSL_ERROR_WANT_READ --> select() untill socket is readable and call SSL_read() again
    • SSL_ERROR_WANT_WRITE --> select() untill socket is writable and call SSL_read() again

    c)n = 0 --> if(SSL_get_shutdown(SSL*) & SSL_RECEIVED_SHUTDOWN) : the other side did clean shutdown, otherwise the shudown was not clean, but the SSL connection is closed you can close the socket (SSL* object too)

  2. When n = SSL_write() returns:

    a)n > 0 --> you have just sent n bytes of data

    b)n < 0 --> err = SSL_get_error() returned

    • SSL_ERROR_WANT_READ --> select() untill socket is readable and call SSL_write() again
    • SSL_ERROR_WANT_WRITE --> select() untill socket is writable and call SSL_write again

    c)n = 0 --> if((err = SSL_get_error(SSL*,err)) == SSL_ERROR_ZERO_RETURN) : the other side did clean shutdown, otherwise the shudown was not clean, but the SSL connection is closed you can close the socket (SSL* object too)

I hope that helps.



来源:https://stackoverflow.com/questions/14378189/how-to-tell-when-no-more-progress-can-be-made-on-an-ssl-connection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!