How to make non-blocking OpenSSL connection?

10,223

Creating a non-blocking socket is a pre-requisite to a non-blocking connect...

The following steps summarize: (see complete description in site linked below)

1) Call the fcntl() API to retrieve the socket descriptor's current flag settings into a local variable.

2) In that local variable, set the O_NONBLOCK (non-blocking) flag on. (being careful not to tamper with the other flags)

3) Call the fcntl() API to set the flags for the descriptor to the value in our local variable.

( read more on non-blocking sockets techniques here )

Assuming an existing socket, the following implements the steps outlined above:

BOOL SetSocketBlockingEnabled(SOCKET fd, BOOL blocking)
{
     if (fd < 0) return FALSE;  
   #ifdef WIN32
       unsigned long mode = blocking ? 0 : 1;
       return (ioctlsocket(fd, FIONBIO, &mode) == 0) ? TRUE : FALSE;
   #else
       int flags = fcntl(fd, F_GETFL, 0);
       if (flags < 0) return false;
       flags = blocking ? (flags&~O_NONBLOCK) : (flags|O_NONBLOCK);
       return (fcntl(fd, F_SETFL, flags) == 0) ? TRUE : FALSE;
   #endif
}

Once you have a non-blocking socket, then see this post explaining how to do a non-blocking connect

Share:
10,223
MrTall394
Author by

MrTall394

Updated on June 04, 2022

Comments

  • MrTall394
    MrTall394 almost 2 years

    I want make a non-blocking OpenSSL connection

    On this connection - if no data available for read, then entire program execution flow make stop on SSL_read(). I want so that if no data available for read it give me the returns values like WANT_READ and i know no more data available.

    char *sslRead (connection *c)
    {
    const int readSize = 1024;
    char *rc = NULL;
    int r;
    int received, count = 0;
    int ReallocSize = 0;
    char buffer[1024];
    
    if (c)
    {
        while (1)
        {
            if (!rc)
            {
                rc = malloc (readSize + 1); 
                if (rc == NULL)
                    printf("the major error have happen. leave program\n");
            }
            else
            {
                ReallocSize = (count + 1) * (readSize + 1);
                rc = realloc (rc, ReallocSize);
            }
    
            // if i have no data available for read after reading data, 
            // this call will not return anything and wait for more data
    
            // i want change this non blocking connections
            received = SSL_read (c->sslHandle, buffer, readSize);
    
            buffer[received] = '\0';
    
    
            if (received <= 0)
            {
                printf(" received equal to or less than 0\n");
                switch (SSL_get_error(c->sslHandle, r))
                {
                case SSL_ERROR_NONE:
                    printf("SSL_ERROR_NONE\n");
                    break;   
                case SSL_ERROR_ZERO_RETURN: 
                    printf("SSL_ERROR_ZERO_RETURN\n");
                    break;   
                case SSL_ERROR_WANT_READ: 
                    printf("SSL_ERROR_WANT_READ\n");
                    break;
                default:
                    printf("error happens %i\n", r); 
                }     
                break;
            }
    
            count++;
        }
    }
    return rc;
    

    }

    here is how i make connection

    connection *sslConnect (void)
    {
       connection *c;
    
       c = malloc (sizeof (connection));
       c->sslHandle = NULL;
       c->sslContext = NULL;
    
       c->socket = tcpConnect ();
       if (c->socket)
       {
        // Register the error strings for libcrypto & libssl
        SSL_load_error_strings ();
        // Register the available ciphers and digests
        SSL_library_init ();
    
        // New context saying we are a client, and using SSL 2 or 3
        c->sslContext = SSL_CTX_new (SSLv23_client_method ());
        if (c->sslContext == NULL)
        ERR_print_errors_fp (stderr);
    
        // Create an SSL struct for the connection
        c->sslHandle = SSL_new (c->sslContext);
        if (c->sslHandle == NULL)
        ERR_print_errors_fp (stderr);
    
        // Connect the SSL struct to our connection
        if (!SSL_set_fd (c->sslHandle, c->socket))
        ERR_print_errors_fp (stderr);
    
        // Initiate SSL handshake
        if (SSL_connect (c->sslHandle) != 1)
        ERR_print_errors_fp (stderr);
        }
        else
        {
         perror ("Connect failed");
        }
    
        return c;
    }
    

    thanks you very much.

  • JasonN
    JasonN about 2 years
    The meat of the question involves OpenSSL, so I find t his not even close to useful. Sure, point out he might not have set the socket to non-block, but that shouldn't be your entire answer.