title: OpenSSL non-blocking sockets SSL_Read() still blocks
body: <p>I have a client/server program written in C++ for windows which I nearly done integrating OpenSSL into.</p>
  
  <p>I do want to state that I have looked over all the other posts similar to my own, and I have not yet found the correct answer to my problem.  Most of the other exmaples are very close to the answer, but I cannot seem to produce the actual result.</p>
  
  <p>For my test case I am simply passing a string of 7 characters from the client to the server using OpenSSL secure sockets every 5 seconds.  I am not sending any other information.  The original problem was that I was not using SSL_read correctly and I was not reading in the apparent extra data that was needed, and the SSL_read would stop responding and the client would lose connection.</p>
  
  <p>After reading all of the other examples I got a couple steps further to accomplishing this, but I could never get the desired result.  I have attempted over 10 types of SSL_read implementations and I cannot get the code to be non-blocking while reading data.  I will post my latest implementation (not incredibly optimized):</p>
  
  <pre><code>int received = -1;
  int tE = 0;
  
      if( tE != SSL_ERROR_WANT_READ &amp;&amp; tE != SSL_ERROR_WANT_WRITE )
      {
          received = SSL_read(sSecureSocket.ssl, buffer, sizeof(buffer)); 
          if( received == -1 )
          {
              tE = SSL_get_error( sSecureSocket.ssl, received );
              if( tE == SSL_ERROR_WANT_READ )
              {
                  int tReadWaiting = 1;
                  while( tReadWaiting )
                  {
                      tReadWaiting = 0;
                      fd_set rfd;
                      FD_ZERO(&amp;rfd);
                      FD_SET(receiveSocket, &amp;rfd);
                      timeval tv = { 0 };
                      select(receiveSocket+1, &amp;rfd, 0, 0, &amp;tv);
                      if (!FD_ISSET(receiveSocket, &amp;rfd))
                      {
                          tReadWaiting = 1;
                      }
                  }
                  received = SSL_read(sSecureSocket.ssl, buffer, sizeof(buffer)); 
              }
          }
      }
  </code></pre>
  
  <p>This code does successfully extract the packet every time it is sent, however as you can see I must use the select() statement once the SSL_ERROR_WANT_READ/WRITE is triggered.  This approach was taken from another thread of this forum, say that you are supposed to read UNTIL the SSL_ERROR_WANT_READ/WRITER are called.  Also, I do use SSL_pending() but it always returns 0 in every case I have, never is it a non-zero number.</p>
  
  <p>The program is written with non-blocking sockets with WSAASyncSelect calls to windows messages.  All of that works fine.</p>
  
  <p>But what happens is the opposite of what I expect.  The code seems to always wait for data which is non existent.  I realize the the SSL sockets are meant to do handshakes at random times as well.  I am just trying to figure out why once I have received that the data from the server, why it seems that SSL_read seems to have data, or select() detects data needs to be be read in between the 5 second intervals in which I send my packet so that the select() loop blocks for the whole time.  Even once the packet is completely read, the next message is called back into the read function and the program itself can never leave this function to do any other processes.</p>
  
  <p>Any help is greatly appreciated, I've never been at my wit's end programming before, this is bringing me very close to it.  </p>
  
  <p><strong>UPDATE 1:</strong></p>
  
  <p>This is the socket listening code:</p>
  
  <pre><code>ctx = sSecureSocket.InitServerCTX();        // initialize SSL 
      sSecureSocket.LoadCertificates(ctx, VGlobal::CURRWORKDIR + "\\openssl2\\" + "mycert.pem", VGlobal::CURRWORKDIR + "\\openssl2\\" + "mycert.pem"); // load certs 
      servSecureSocket = sSecureSocket.OpenListener(39245);    // create server socket 
  </code></pre>
  
  <p>This is called when the socket is accepted on the server:</p>
  
  <pre><code>//Always connect as a secure socket first
  struct sockaddr_in addr;
  socklen_t len = sizeof(addr);
  SSL *ssl;
  
  receiveSocket = accept(servSecureSocket, (struct sockaddr*)&amp;addr, &amp;len);  // accept connection as usual 
  printf("Connection: %s:%d\n",inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
  sSecureSocket.ssl = SSL_new(ctx);              // get new SSL state with context 
  SSL_set_fd(sSecureSocket.ssl, receiveSocket);      // set connection socket to SSL state 
  sSecureSocket.Servlet(sSecureSocket.ssl);         // service connection 
  </code></pre>
  
  <p>These are the functions:</p>
  
  <pre><code>//-----------------------------------------------------
  int SecureSocket::OpenListener(int port)
  {   int sd;
  struct sockaddr_in addr;
  
  WSADATA wsadata;
  int error = WSAStartup( 0x0202, &amp;wsadata );
  
  if( error )
      return false;
  
  sd = socket(PF_INET, SOCK_STREAM, 0);
  //bzero(&amp;addr, sizeof(addr));
  memset(&amp;addr, 0, sizeof(addr));
  addr.sin_family = AF_INET;
  addr.sin_port = htons(port);
  addr.sin_addr.s_addr = INADDR_ANY;
  if ( bind(sd, (struct sockaddr*)&amp;addr, sizeof(addr)) != 0 )
  {
      perror("can't bind port");
     // abort();
  }
  if ( listen(sd, 10) != 0 )
  {
      perror("Can't configure listening port");
     // abort();
  }
  return sd;
  }
  
  //-----------------------------------------------------
  SSL_CTX* SecureSocket::InitServerCTX(void)
  {   
  SSL_METHOD *method;
  SSL_CTX *ctx;
  
  OpenSSL_add_all_algorithms();  /* load &amp; register all cryptos, etc. */
  SSL_load_error_strings();   /* load all error messages */
  ctx = SSL_CTX_new(SSLv23_server_method());
  if ( ctx == NULL )
  {
      ERR_print_errors_fp(stderr);
  }
  return ctx;
  }
  
  //-----------------------------------------------------
  void SecureSocket::LoadCertificates(SSL_CTX* ctx, CString CertFile, CString KeyFile)
  {
  /* set the local certificate from CertFile */
  if ( SSL_CTX_use_certificate_file(ctx, CertFile, SSL_FILETYPE_PEM) &lt;= 0 )
  {
      ERR_print_errors_fp(stderr);
  }
  /* set the private key from KeyFile (may be the same as CertFile) */
  if ( SSL_CTX_use_PrivateKey_file(ctx, KeyFile, SSL_FILETYPE_PEM) &lt;= 0 )
  {
      ERR_print_errors_fp(stderr);
  }
  /* verify private key */
  if ( !SSL_CTX_check_private_key(ctx) )
  {
      fprintf(stderr, "Private key does not match the public certificate\n");
  }
  }
  
  //-----------------------------------------------------
  void SecureSocket::ShowCerts(SSL* ssl)
  {   X509 *cert;
  char *line;
  
  cert = SSL_get_peer_certificate(ssl); /* Get certificates (if available) */
  if ( cert != NULL )
  {
      printf("Server certificates:\n");
      line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
      printf("Subject: %s\n", line);
      free(line);
      line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
      printf("Issuer: %s\n", line);
      free(line);
      X509_free(cert);
  }
  else
      printf("No certificates.\n");
  }
  
  //-----------------------------------------------------
  void SecureSocket::Servlet(SSL* ssl) /* Serve the connection -- threadable */
  {
  int acceptDone = SSL_accept(ssl);
  
  //If this blocking this will be done immediately, if it is not we must loop until it is complete
  while( acceptDone &lt; 1 )
  {
      acceptDone = SSL_accept(ssl);
  }
  
  ShowCerts(ssl);        /* get any certificates */
  }
  </code></pre>