3

I am trying to use the select function to have non-blocking connection from a client to server.I found a tutorial with some code and tried to adapt to this:

...
sockfd = socket(AF_INET, SOCK_STREAM, 0);
err = connect(sockfd,(struct sockaddr*)&sa,sizeof(sa));
...
SSL_set_fd(pssl,sockfd);
err = SSL_connect_nonb(pssl,sockfd,60);
if(err <=0 ){
    printf("SSL_connect:%s\n",ERR_error_string(SSL_get_error(pssl,err),NULL));
    return -1;
}
...

The SSL_connect_nonb function is defined as bellow:

int SSL_connect_nonb(SSL*pssl,int sockfd, int nsec)
{
    int flags, error;
    socklen_t len;
    fd_set rset, wset;
    struct timeval tval;
    flags = fcntl(sockfd, F_GETFL, 0);
    fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
    int err = SSL_connect(pssl);
    int err2 = SSL_get_error(pssl,err);
    switch(err2) {
            default:
                printf("SSL_connect err=%s\n",ERR_error_string(err2,0));
                return -1;
                break;
            case SSL_ERROR_WANT_READ:
            case SSL_ERROR_WANT_WRITE:
                break;
    }
    FD_ZERO(&rset);
    FD_ZERO(&wset);
    FD_SET(sockfd, &rset);
    FD_SET(sockfd, &wset);
    tval.tv_sec = nsec;
    tval.tv_usec = 0;
    if (select(sockfd+1, &rset, &wset, NULL,nsec ? &tval:NULL) == 0) {
        return -1;
    }
    if(FD_ISSET(sockfd,&rset) || FD_ISSET(sockfd, &wset )) {
        len = sizeof(error);
        if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0){
            return -1;
        }
    }else{
        printf("sockfd  not set\n");
        return -1;
    }
    fcntl(sockfd, F_SETFL, flags);
    if (error) {
        return -1;
    }
    return 1;
}

The sockfd is correct with connect,the problem is that in SSL_connect_nonb the select function return avalue=1 (actually the condition FD_ISSET(sockfd, &wset) is successful all time),but if I use blocking method as this :

....    
SSL_set_fd(pssl,sockfd);
err = SSL_connect(pssl);
if(err <=0 ){
    printf("SSL_connect:%s\n",ERR_error_string(SSL_get_error(pssl,err),NULL));
    return -1;
}
...

the value of err is 0 because the SSL_connect is not successful, so, how to do with SSL_connect on non blocking socket by calling select function?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
user2664403
  • 31
  • 1
  • 3

1 Answers1

5

SSL_connect(), aka SSL client handshake, is a complicated process, which requires several roundtrip with servers. So, when you run SSL_connect() on a non-blocking socket, it's not enough to just run it only once. When you get SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, you must retry SSL_connect() again, until it succeeded or failed with other errors.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
GlacJAY
  • 159
  • 4
  • 8