nonblocking BIO_do_connect blocked when there is n

2019-05-12 05:59发布

问题:

I am using Openssl-0.9.8x as follows:

bio = BIO_new_ssl_connect(ctx);
BIO_get_ssl(bio, & ssl);
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
BIO_set_nbio(bio, 1);
in_addr_t serverIP =  inet_addr(HTTPS_SERVER_IP);
BIO_set_conn_ip(bio, &serverIP );
BIO_set_conn_port(bio, HTTPS_SERVER_PORT_STR);
while(1) {
    printf("BIO_do_connect start>>>>\n");
    if(BIO_do_connect(bio) <= 0 && BIO_should_retry(bio)) {
        sleep(1);
        printf("BIO_do_connect retry>>>>\n");
    }
    else {
        printf("Connect success.\n");
    }
}

It works fine when the internet connection is OK (i.e. it can connect to the server). But, when the internet connection is limited (i.e. it can't connect to the server), the BIO_do_connect() is blocked after one or more times of retry. The output as follows:

BIO_do_connect start>>>>
BIO_do_connect retry>>>>
BIO_do_connect start>>>>
BIO_do_connect retry>>>>
BIO_do_connect start>>>>

Finally, it is blocked in BIO_do_connect(...)? why this happened?

回答1:

It is probably your use of SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY).

From the 0.9.8 man page:

SSL_MODE_AUTO_RETRY

Never bother the application with retries if the transport is blocking. If a renegotiation take place during normal operation, a SSL_read() or SSL_write() would return with -1 and indicate the need to retry with SSL_ERROR_WANT_READ. In a non-blocking environment applications must be prepared to handle incomplete read/write operations. In a blocking environment, applications are not always prepared to deal with read/write operations returning without success report. The flag SSL_MODE_AUTO_RETRY will cause read/write operations to only return after the handshake and successful completion.

The effect of SSL_MODE_AUTO_RETRY is to automatically retry operations that would otherwise return back to application code (even when the using blocking connections). It doesn't make any sense to use it when you want non-blocking operation.

Try removing that line completely.

By the way 0.9.8 is out of support and is no longer receiving security updates. You really ought to upgrade to a more recent version.



回答2:

Add the following:

in_addr_t serverIP =  inet_addr(HTTPS_SERVER_IP);
BIO_set_conn_ip(bio, &serverIP );
BIO_set_conn_port(bio, HTTPS_SERVER_PORT_STR);