How to make non-blocking OpenSSL connection?
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
MrTall394
Updated on June 04, 2022Comments
-
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 about 2 yearsThe 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.