C++ IO完成端口和OpenSSL

C++ IO完成端口和OpenSSL,c++,openssl,C++,Openssl,我有一些使用OpenSSL进行通信的遗留代码。与任何其他会话一样,它使用SSL函数进行握手,然后通过TCP进行加密通信。我们最近将代码更改为使用IO完成端口。它的工作方式与OpenSSL相反。基本上,我很难将我们的安全通信代码从完全使用OpenSSL迁移到IOCP套接字和OpenSSL加密 是否有人/有人知道任何可能帮助我完成此任务的参考资料? TLS握手如何在IOCP上工作?为了使用OpenSSL进行加密,您应该研究一下,但要做自己的套接字IO,您基本上要做的是创建一个内存BIO,在可用时读取

我有一些使用OpenSSL进行通信的遗留代码。与任何其他会话一样,它使用SSL函数进行握手,然后通过TCP进行加密通信。我们最近将代码更改为使用IO完成端口。它的工作方式与OpenSSL相反。基本上,我很难将我们的安全通信代码从完全使用OpenSSL迁移到IOCP套接字和OpenSSL加密

是否有人/有人知道任何可能帮助我完成此任务的参考资料?
TLS握手如何在IOCP上工作?

为了使用OpenSSL进行加密,您应该研究一下,但要做自己的套接字IO,您基本上要做的是创建一个内存BIO,在可用时读取和写入套接字数据,并将其附加到SSL上下文

每次执行SSL_write调用时,您都会调用内存BIO,查看它的读取缓冲区中是否有数据,然后读取并发送数据。 相反,当数据通过io完成端口机制到达套接字时,将其写入BIO并调用SSL_read来读取数据。SSL_read可能会返回一个错误代码,指示它在握手中的状态,这通常意味着它生成了更多要写入的数据—您可以通过再次读取内存BIO来处理这些数据


要创建SSL会话,请执行以下操作:

// This creates a SSL session, and an in, and an out, memory bio and
// attaches them to the ssl session.
SSL* conn = SSL_new(ctx);
BIO* bioIn = BIO_new(BIO_s_mem());
BIO* bioOut = BIO_new(BIO_s_mem());
SSL_set_bio(conn,bioIn,bioOut);
// This tells the ssl session to start the negotiation.
SSL_set_connect_state(conn);
当我从网络层接收数据时:

// buf contains len bytes read from the socket.
BIO_write(bioIn,buf,len);
SendPendingHandshakeData();
TryResendBufferedData(); // see below
int cbPlainText;
while( cbPlainText = SSL_read(ssl,&plaintext,sizeof(plaintext)) >0)
{
  // Send the decoded data to the application
  ProcessPlaintext(plaintext,cbPlaintext);
}
当我从要发送的应用程序接收数据时,您需要准备好SSL_写入失败,因为正在进行握手,在这种情况下,您将缓冲数据,并在将来收到一些数据后再次尝试发送数据

if( SSL_write(conn,buf,len) < 0)
{
  StoreDataForSendingLater(buf,len);
}
SendPendingHandshakeData();

简而言之,这就是过程。代码示例并不完整,因为我必须从一个更大的库中提取它们,但我相信它们足以让人们开始使用SSL。在实际代码中,当SSL_读/写/BIO_读/写失败时,最好调用SSL_get_error并根据结果决定要执行的操作:SSL_error_WANT_read是重要的,这意味着您无法SSL_写入更多数据,因为它需要您首先读取并发送BIOOT BIO中的挂起数据。

是,在我发布的链接中有一些例子。即使它没有完全回答问题,boost::asio也有足够的惊人之处,值得一个+1。这是一个很好的例子。在我是服务器的情况下,我会用SSL\u set\u connect\u state()调用代替SSL\u set\u accept\u state()调用吗?我只使用过客户端套接字和OpenSSL,但从我对文档的理解来看,应该很简单。好的。另外,为什么在任何地方调用SendPendingHandshakeData()都是明智之举?我假设握手只在会话开始时发生一次。还是每次发送数据包时都会发生这种情况?理论上,如果连接的另一端有策略要求,ssl握手可以在任何时候重新触发。另外,这样编写代码可以很好地实现无状态,因此不需要从“协商”状态转到“连接”状态。
while(cbPending = BIO_ctrl_pending(bioOut))
{
  int len = BIO_read(bioOut,buf,sizeof(buf));
  SendDataViaSocket(buf,len); // you fill this in here.
}