extern "C" int iocba_receive_data(
    void* tls_channel,
    char* data,
    int length )
{
    Botan::TLS::Channel* channel = (Botan::TLS::Channel*) tls_channel;
    try {
        //printf("Before taking data=%p \n", channel);
        size_t more_data_required = channel->received_data( (const unsigned char*) data, length);
        //printf("More data required %d \n", more_data_required);
        //printf("After taking data=%p \n", channel);
    } catch (std::exception const& e)
    {
        // TODO: control messages
        printf("BotanTLS engine instance crashed (normal if ALPN didn't go well): %s \n", e.what());
        return -1;
    }
    return 0;
}
// Called with encrypted data received from the peer. 
extern "C" DLL_PUBLIC int32_t iocba_receive_data(
    buffers_t* buffers,
    char* in_data,
    uint32_t in_length,
    char* out_enc_to_send,
    uint32_t *enc_to_send_length,

    char* out_cleartext_received,
    uint32_t *cleartext_received_length
    )
{
    //TRACE("Entering iocba_receive_data\n");
    Botan::TLS::Channel* channel = buffers -> channel;
    //
    buffers -> enc_cursor = out_enc_to_send;
    buffers -> enc_end    = out_enc_to_send + *enc_to_send_length;
    //
    buffers -> clr_cursor = out_cleartext_received;
    buffers -> clr_end    = out_cleartext_received + *cleartext_received_length;
    //TRACE("Botan receives data\n");
    try {
        size_t more_data_required =
            channel->received_data( (const unsigned char*) in_data, in_length);
        buffers->check_readiness();
    }
    catch (buffer_override_exception_t const& e)
    {
        TRACE("Buffer override at iocba_receive_data!! (received %d bytes for cleartext and %d bytes for encoded)\n", *cleartext_received_length, *enc_to_send_length);
        return -1;
    }
    catch (Botan::TLS::TLS_Exception const& e)
    {
        if (e.type() == Botan::TLS::Alert::INAPPROPRIATE_FALLBACK)
        {
            TRACE("BotanTLS engine instance likely crashed before: %s \n", e.what());
            return -1;
        } else
        {
            TRACE("BotanTLS engine instance crashed (normal if ALPN didn't go well): %s \n", e.what());
            return -1;
        }
    }
    catch (std::exception const& e)
    {
        // TODO: control messages
        TRACE("BotanTLS engine crashed with generic exception: %s \n", e.what());
        return -1;
    }

    *enc_to_send_length = (uint32_t) (
        buffers -> enc_cursor 
        - out_enc_to_send );
    //TRACE("Returning %d bytes \n", *enc_to_send_length);
    *cleartext_received_length = (uint32_t) (
        buffers -> clr_cursor 
        - out_cleartext_received 
        );
    //TRACE("Returning %d bytes of cleartext \n", *cleartext_received_length);
    // So that we get a clean segfault if we do something wrong
    buffers-> clear_cursors();
    if ( buffers -> alert_produced )
    {
        if ( buffers -> alert_is_fatal || buffers -> peer_closed_transport)
        {
            // If I don't get this message we are in trouble...
            // TRACE("Alert assimilated as part of decryption call\n");
            return -1;
        }
    }

    return 0;
}