OpenSSL and signals
OpenSSL and signals
send
、receive
等Socket功能可被信号中断。因此,需要一些额外的代码,例如检查errno == EINTR
。这在相应的手册页中有描述。
我想知道当使用OpenSSL函数时如何工作,例如SSL_write
, SSL_read
。它们的手册页没有提到任何关于信号的内容。我也试着在谷歌上搜索这个,但没有运气。你知道OpenSSL是内部处理信号,还是需要一些额外的代码?如果是,如何检查函数调用是否被信号中断?
更新:
看起来OpenSSL不处理重试。它只在BIO对象上设置"应该重试"标志。所以我需要使用这样的东西来检测调用是否被中断,是否需要重试:
int result = SSL_write(ssl, buff, length);
if ((result < 0) && BIO_should_retry(SSL_get_wbio(ssl)))
// need to retry
int result = SSL_read(ssl, buff, length);
if ((result < 0) && BIO_should_retry(SSL_get_rbio(ssl)))
// need to retry
作为一个库,OpenSSL不能对使用它的特定程序如何处理信号做出任何假设。因此,它需要处理接收到信号时系统调用被中断的情况。
检查重试失败的read()
是否有意义在OpenSSL中实现。
如果BIO_read()
(或BIO_write()
)失败,则使用BIO_should_retry()
。
示例如下:http://cvs.openssl.org/rlog?f=openssl/demos/bio/sconnect.c
实现的相关代码如下:
static int sock_read(BIO *b, char *out, int outl)
{
int ret=0;
if (out != NULL)
{
clear_socket_error();
ret=readsocket(b->num,out,outl);
BIO_clear_retry_flags(b);
if (ret <= 0)
{
if (BIO_sock_should_retry(ret))
BIO_set_retry_read(b);
}
}
return(ret);
}
相关的引用函数在这里:
(get_last_socket_error()
在大多数IXish平台上返回errno
)
int BIO_sock_should_retry(int i)
{
int err;
if ((i == 0) || (i == -1))
{
err=get_last_socket_error();
#if defined(OPENSSL_SYS_WINDOWS) && 0 /* more microsoft stupidity? perhaps not? Ben 4/1/99 */
if ((i == -1) && (err == 0))
return(1);
#endif
return(BIO_sock_non_fatal_error(err));
}
return(0);
}
int BIO_sock_non_fatal_error(int err)
{
switch (err)
{
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_NETWARE)
# if defined(WSAEWOULDBLOCK)
case WSAEWOULDBLOCK:
# endif
# if 0 /* This appears to always be an error */
# if defined(WSAENOTCONN)
case WSAENOTCONN:
# endif
# endif
#endif
#ifdef EWOULDBLOCK
# ifdef WSAEWOULDBLOCK
# if WSAEWOULDBLOCK != EWOULDBLOCK
case EWOULDBLOCK:
# endif
# else
case EWOULDBLOCK:
# endif
#endif
#if defined(ENOTCONN)
case ENOTCONN:
#endif
#ifdef EINTR
case EINTR:
#endif
#ifdef EAGAIN
# if EWOULDBLOCK != EAGAIN
case EAGAIN:
# endif
#endif
#ifdef EPROTO
case EPROTO:
#endif
#ifdef EINPROGRESS
case EINPROGRESS:
#endif
#ifdef EALREADY
case EALREADY:
#endif
return(1);
/* break; */
default:
break;
}
return(0);
}
详情见sock_read()
待检:http://cvs.openssl.org/rlog?f=openssl/crypto/bio/bss_sock.c
(引用的来源以及使用的缩进来自1.0.1e版)
如果一个信号中断了导致它返回错误的系统调用,那么调用SSL函数将返回一个错误指示(例如-1),并且SSL_get_error
可以根据SSL的状态返回任意数量的错误。
最有可能的是,它将返回SSL_ERROR_WANT_READ
, SSL_ERROR_WANT_WRITE
或SSL_ERROR_SYSCALL
(希望errno
中有EINTR
)。其他错误,如SSL_ERROR_WANT_CONNECT
、SSL_ERROR_WANT_ACCEPT
、SSL_ERROR_WANT_X509_LOOKUP
和SSL_ERROR_SSL
,都是可能的,具体取决于您在做什么。
对于OpenSSL v1.0.2j, SSL_get_error
返回的错误通常取决于SSL结构的读写状态及其底层BIOs。通常, SSL_read
为SSL_ERROR_WANT_READ
, SSL_write
为SSL_ERROR_WANT_WRITE
。然而,在初始握手期间,可能在重新协商期间(这可能发生在对SSL_read
或SSL_write
的正常调用中),当低级调用被信号中断时,SSL_get_error
看起来可以返回SSL_ERROR_SYSCALL
, EINTR
应该在errno
中。此外,在重新协商过程中,SSL_read
产生SSL_ERROR_WANT_WRITE
, SSL_write
产生SSL_ERROR_WANT_READ
的可能性始终存在。
我不建议您尝试像在更新中那样直接咨询底层BIOs。相反,请查看SSL_get_error
,如果这是一个非致命错误,则重试或采取其他适当的操作。
- C++核心准则 C35 对于接口类"A base class destructor should be either public and virtual, or protected and nonv
- 为什么C++逐位AND运算符在不同大小的操作数中表现为这样
- 为什么 Clang 不允许"and"作为函数名称?
- 位阵列上的快速AND运算
- 是否可以在 C++03 中定义'move-and-swap idiom'等效项
- BoostPython and CMake
- OpenSSL BIO and SSL_read
- Gurobi GRBModel and GRBmodel in C++
- std::visit and std::variant usage
- SHBrowseForFolder with BIF_BROWSEFORCOMPUTER and SHGetPathFr
- Directx12 and keystrokes
- different between int **arr =new int [ n]; and int a[i][j]?
- C++ getenv and setenv
- Inference pytorch C++ with alexnet and cv::imread image
- Visual Studio 2019 C++ and std::filesystem
- 保证逻辑 AND 表达式中的函数调用
- std::getline and posix signals
- QT QNetworkAccessManager and Signals
- LeapMotion, Qt and signals
- OpenSSL and signals