以下是一些示例代码,展示了我如何使用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
吗?)
一个好的下限也适用于我,我的问题是我需要报告要读取多少数据到我上面的层,并且它不会将控制权返回给我,直到它读取了那么多数据(和我不想退化为1字节读取。)
我知道SSL_Read
和SSL_Write
可以交替阅读&由于握手等而写,但我对内部正在进行的“当前”读取感兴趣。
如果无法使用标准BIO_s_mem
,我认为如果我编写了自己的BIO,并且记得上次读取请求失败的大小,那么就可以完成。所以任何指向文档的指针都可以编写自定义BIO(据我所知,OpenSSL支持)也将受到赞赏。
答案 0 :(得分:0)
感谢CristiFati建议的BIO_set_callback,它似乎有效。如果你想对答案做出评论,我会接受,但我想把这些细节放在后面。
在我的'SSLSocket'课程中:
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()中写入多少。