Hallo

We habe a problem with our c++ win32 application. We are using WinSockets 
and write/read data with openssl. 95% are working fine. But when the 
response takes longer, the application is blocked.

Now i've try to make the socket non-blocked, but it doesen't works. Here 
are a few code-lines of our application:

...
    m_client = new TClientSocket(Application->MainForm);
    m_client->ClientType = ctNonBlocking;   (we are using non-blocking 
sockets)
...

nt __fastcall TcpFeSession::InitCTX()
{
    int sslStatus         = 0;
    AnsiString sslIniFile = FOSUP_SSL_CONFIG_FILE;

    // Init. globale Informationen
    SSL_library_init();
    SSL_load_error_strings();

    // Erstellung des context
    meth = TLSv1_method();
    ctx  = SSL_CTX_new(meth);
        if (ctx == NULL)
        {
        m_foRegistry->LOG_INFO("ERROR: InitCTX -> SSL_CTX_new() 
failed...");
        return -1;
    }

    ERR_clear_error();
    sslStatus = SSL_CTX_load_verify_locations(ctx, sslIniFile.c_str(), 
CADIR);
    if (!sslStatus)
    {
        m_foRegistry->LOG_INFO("ERROR: InitCTX -> 
SSL_CTX_load_verify_locations(" + sslStatus + ") ...");
        return -1;
    }

    sslStatus = SSL_CTX_set_default_verify_paths(ctx);
    if (!sslStatus)
    {
        m_foRegistry->LOG_INFO("ERROR: InitCTX -> 
SSL_CTX_set_default_verify_paths(" + sslStatus + ") ...");
        return -1;
    }

    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, 
&TcpFeSession::verify_callback);
    SSL_CTX_set_verify_depth(ctx, 4);
    SSL_CTX_set_options(ctx, SSL_OP_ALL);
 
    sslStatus = SSL_CTX_set_cipher_list(ctx, CIPHER_LIST);
    if ( !sslStatus) {
        m_foRegistry->LOG_ERROR("ERROR: InitCTX -> 
SSL_CTX_set_cipher_list() " +
                                SSL_get_error(ssl, sslStatus) +
                                " ...");
        return -1;
    }

    m_foRegistry->LOG_INFO("INFO: SSL InitCTX -> successful...");
    return 1;
}

int __fastcall TcpFeSession::OpenSSL(TCustomWinSocket *Socket)
{
    int sslStatus     = 0;
    int sslError      = 0;
    int extcount;
    int sock;
    u_long nonblocking = 1;


    std::string sHost = m_client->Host.c_str();
    std::ostringstream oss;
    oss << sHost << ":" << m_client->Port;
    std::string myConnect(oss.str());

        // SSL Struktur erstellen
    ssl = SSL_new(ctx);
        if ( !ssl ) {
        m_foRegistry->LOG_ERROR("ERROR: OpenSSL -> SSL_new() ...");
        return -1;
    }

    // Neue Verbindung erstellen
    conn = BIO_new_connect(const_cast<char*>(myConnect.c_str()));
    if (!conn)
    {
        m_foRegistry->LOG_ERROR("ERROR: OpenSSL -> BIO_new_connect() 
...");
        return -1;
    }

    if (BIO_do_connect(conn) <= 0)
    {
        m_foRegistry->LOG_ERROR("ERROR: OpenSSL -> BIO_do_connect() ...");
        return -1;
    }

    BIO_set_fd(conn, sock, BIO_NOCLOSE);
    SSL_set_bio(ssl, conn, conn);

    // If the socket is in non-blocking mode set the BIO
    // to non-blocking mode (blocking is the default)
    // Set both the read and write BIO's to non-blocking mode
    BIO_set_nbio(SSL_get_rbio(ssl), 1);
    BIO_set_nbio(SSL_get_wbio(ssl), 1);

    // Connecting / Handshake
    sslStatus = SSL_connect(ssl);
        sslError  = SSL_get_error(ssl, sslStatus);
    switch(sslError)
        {
                case SSL_ERROR_ZERO_RETURN:
             m_foRegistry->LOG_ERROR("ERROR: OpenSSL -> SSL_connect() peer 
close ssl connection ...");
                 return -1;
       default:
                break;
    }
    // SSL_set_connect_state(ssl);

    // START: Server Zertikikat annehmen
    server_cert = SSL_get_peer_certificate(ssl);
        if ( !server_cert ) {
        m_foRegistry->LOG_INFO("INFO: OpenSSL -> 
SSL_get_peer_certificate() The SSL server does not have certificate...");
    }

    if(SSL_get_verify_result(ssl) != X509_V_OK)
    {
        m_foRegistry->LOG_ERROR("ERROR: OpenSSL -> SSL_get_verify_result() 
...");
        return -1;
    }
    m_foRegistry->LOG_INFO("INFO: OpenSSL successful...");
    return 1;
}

void __fastcall TcpFeSession::ClientRead(TObject *Sender,
                                         TCustomWinSocket *Socket)
{
    int readCount;
...

    unsigned nread;

    for (nread = 0;  nread < bytesToRead;  nread += readCount)
    {
        unsigned remaining = std::min(bytesToRead - nread, 4088u);
        while (0 >= (readCount = SSL_read(ssl, readBuffer + nread, 
remaining))){
            switch (SSL_get_error(ssl, readCount))
            {
                case SSL_ERROR_NONE:
                    m_foRegistry->LOG_INFO("INFO: ClientRead -> SSL_read() 
Header successful (" + readCount + ")...");
                    break;
                case SSL_ERROR_WANT_WRITE:
                    m_foRegistry->LOG_ERROR("ERROR: ClientRead -> 
SSL_read( " +
                                            readCount +
                                            " ) Header failed (write W 
BLOCK) ...");
                    break;
                case SSL_ERROR_WANT_READ:
                    m_foRegistry->LOG_ERROR("ERROR: ClientRead -> 
SSL_read( " +
                                            readCount +
                                            " ) Header failed (write R 
BLOCK) ...");
                    break;
                case SSL_ERROR_WANT_X509_LOOKUP:
                    m_foRegistry->LOG_ERROR("ERROR: ClientRead -> 
SSL_read( " +
                                            readCount +
                                            " ) Header failed (write X 
BLOCK) ...");
                    break;
                case SSL_ERROR_ZERO_RETURN:
                    m_foRegistry->LOG_ERROR("ERROR: ClientRead -> 
SSL_read( " +
                                            readCount +
                                            " ) Header failed (shutdown) 
...");
                    break;
                case SSL_ERROR_SYSCALL:
                    m_foRegistry->LOG_ERROR("ERROR: ClientRead -> 
SSL_read( " +
                                            readCount +
                                            " ) Header failed (write 
socket error) ...");
                    break;
                case SSL_ERROR_SSL:
                    m_foRegistry->LOG_ERROR("ERROR: ClientRead -> 
SSL_read( " +
                                            readCount +
                                            " ) Header failed (ssl error) 
...");
                    break;
                default:
                    break;
            }
        }

        if (readCount <= 0)
            break;
        Application->ProcessMessages();
    }

...

Now my question! What i must done, that the ssl_read function dosent 
blocked. I've try to make a select(), or using ssl_pending() and many 
other things, but nothing works?

Please can you help me?

Best regards, Dirk


---------------------------------------------------------------------------
Telekurs Card Solutions AG
Dirk Platte
Karl Neuhaus-Strasse 40 
CH-2502 Biel

Tel.:   +41 32 328 78 69
Fax:    +41 32 328 78 12
Mobile: +41 79 287 12 74
E-Mail: [EMAIL PROTECTED]
WWW:    www.telekurs-card-solution.ch
---------------------------------------------------------------------------

This e-mail may contain confidential and privileged information.
If you are not the intended recipient, please notify the sender and delete
this e-mail immediately.

Reply via email to