在 OpenSSL 中使用内存 BIO 时,如何找到输入 BIO 的 'needed size'?

When using memory BIOs with OpenSSL, how can you find the 'needed size' for the input BIO?

下面是一些示例代码,展示了我如何使用 OpenSSL:

BIO *CreateMemoryBIO() {
    if (BIO *bio = BIO_new(BIO_s_mem())) {
        BIO_set_mem_eof_return(bio, -1);    
        return bio;
    }
    throw std::runtime_error("Could not create memory BIO");
}

m_readBIO = CreateMemoryBIO();
m_writeBIO = CreateMemoryBIO();
SSL_set_bio(m_ssl, m_readBIO, m_writeBIO);

现在,如果我执行 SSL_Read,我得到 SSL_ERROR_WANT_READ,有没有办法让我找出它尝试在内部读取了多少(换句话说,有多少我需要用 BIO_write 写到 m_readBIO 才能满足 SSL_Read 吗?)

一个好的下限对我也适用,我的问题是我需要向我上面的层报告要读取多少数据,它不会 return 控制我,直到它有读取那么多数据(我不想退化为 1 字节读取)。

我知道 SSL_ReadSSL_Write 可能由于握手等原因交替读取和写入,但我对正在完成的 'current' 读取感兴趣内部。

如果无法使用标准 BIO_s_mem,我认为如果我编写自己的 BIO 是可以做到的,'remembered' 最后一个失败的读取请求的大小,所以任何指向编写自定义 BIO 的文档的指针(据我所知,OpenSSL 支持)也将不胜感激。

感谢 CristiFati 的建议 BIO_set_callback,它似乎有效。如果你想把你的评论变成一个答案,我会接受,但我想把细节放在这里以供后代使用。

在我的 'SSLSocket' class:

in the constructor:
BIO_set_callback(m_readBIO, &BIOCallback);
BIO_set_callback_arg(m_readBIO, reinterpret_cast<char*>(this));

long SSLSocket::BIOCallback(
    BIO *in_bio,
    int in_operation,
    const char* in_arg1,
    int in_arg2,
    long in_arg3,
    long in_returnValue)
{
    // in_bio isn't provided for BIO_CB_FREE.
    if (BIO_CB_FREE == in_operation)
    {
        return in_returnValue;
    }

    assert(in_arg1);

    return reinterpret_cast<SSLSocket*>(BIO_get_callback_arg(in_bio))->DoBIOCallback(
        in_bio,
        in_operation,
        in_arg1,
        in_arg2,
        in_arg3,
        in_returnValue);

long SSLSocket::DoBIOCallback(
    BIO *in_bio,
    int in_operation,
    const char* in_arg1,
    int in_arg2,
    long in_arg3,
    long in_returnValue)
{
    UNUSED(in_arg3);

    // We only care about the return callback for BIO_read()
    if ((BIO_CB_READ | BIO_CB_RETURN) == in_operation)
    {
        const int shouldRetry = BIO_should_retry(in_bio);
        const int bytesRequested = in_arg2;
        assert(bytesRequested > 0);

        if ((in_returnValue <= 0) && shouldRetry)
        {
            m_needBytes = bytesRequested;
        }
        else if ((in_returnValue > 0) && (in_returnValue < bytesRequested) && shouldRetry)
        {
            m_needBytes = bytesRequested - in_returnValue;
        }
        else
        {
            m_needBytes = 0;
        }
    }

    return in_returnValue;
}

然后我用m_needBytes决定在BIO_write()中写多少。