如何结合SSL_read和epoll?
How to combine SSL_read and epoll?
我正在用基于事件的网络库(使用 epoll)编写一个 HTTP 代理服务器。
假设有一个快速的 HTTPS 上游和一个慢速的 HTTP(S) 下游。所以我必须将上游数据存储到缓冲区,并在缓冲区已满时从网络库中分离上游读取事件。
但正如我们所知,SSL_read
可能 return 部分数据。所以考虑以下情况:
- 缓冲区大小为
32
并在网络库上附加读取事件
- 上游发送
32
字节,整个 HTTP 消息是 32
字节
- 网络库调用读取事件回调
- 调用
SSL_read(ssl, buf, 32)
和 SSL_read
returns 16
- 向下游发送
16
字节并在网络库上附加读取事件
- 永远不会调用读取回调,因为剩余的 16 个字节在 openssl 缓冲区中并且没有来自上游的更多字节
那么有什么好的解决办法吗?
OpenSSL 较旧的基于 SSL 的 API 不遵循您尝试使用的传统套接字 I/O 事件模型。
使用非阻塞套接字时,您不应在调用 SSL_read()
之前等待套接字读取事件。您应该无条件地调用 SSL_read()
并让它通过返回 SSL_ERROR_WANT_READ
错误来告诉您何时需要来自套接字的更多数据。只有这样,您才应该在再次调用 SSL_read()
之前等待套接字读取事件(如果它 returns SSL_ERROR_WANT_WRITE
,则等待套接字写入事件)。
如果您想使用传统的套接字事件来驱动您的 reading/writing,请改用 OpenSSL 的更新的基于 BIO 的 API。使用 BIO 对将接收到的加密字节推送到 OpenSSL 引擎,并让它在读取时将解密字节推送给您,反之亦然。然后你可以随心所欲地处理套接字 I/O 。
我正在用基于事件的网络库(使用 epoll)编写一个 HTTP 代理服务器。
假设有一个快速的 HTTPS 上游和一个慢速的 HTTP(S) 下游。所以我必须将上游数据存储到缓冲区,并在缓冲区已满时从网络库中分离上游读取事件。
但正如我们所知,SSL_read
可能 return 部分数据。所以考虑以下情况:
- 缓冲区大小为
32
并在网络库上附加读取事件 - 上游发送
32
字节,整个 HTTP 消息是32
字节 - 网络库调用读取事件回调
- 调用
SSL_read(ssl, buf, 32)
和SSL_read
returns16
- 向下游发送
16
字节并在网络库上附加读取事件 - 永远不会调用读取回调,因为剩余的 16 个字节在 openssl 缓冲区中并且没有来自上游的更多字节
那么有什么好的解决办法吗?
OpenSSL 较旧的基于 SSL 的 API 不遵循您尝试使用的传统套接字 I/O 事件模型。
使用非阻塞套接字时,您不应在调用 SSL_read()
之前等待套接字读取事件。您应该无条件地调用 SSL_read()
并让它通过返回 SSL_ERROR_WANT_READ
错误来告诉您何时需要来自套接字的更多数据。只有这样,您才应该在再次调用 SSL_read()
之前等待套接字读取事件(如果它 returns SSL_ERROR_WANT_WRITE
,则等待套接字写入事件)。
如果您想使用传统的套接字事件来驱动您的 reading/writing,请改用 OpenSSL 的更新的基于 BIO 的 API。使用 BIO 对将接收到的加密字节推送到 OpenSSL 引擎,并让它在读取时将解密字节推送给您,反之亦然。然后你可以随心所欲地处理套接字 I/O 。