OpenSSL库允许使用SSL_read从底层套接字读取并使用SSL_write写入它。这些函数可能会返回SSL_ERROR_WANT_READ或SSL_ERROR_WANT_WRITE,具体取决于它们的ssl协议需求(例如,重新协商连接时)。
我真的不明白API希望我对这些结果做些什么。
对接受客户端连接的服务器应用程序进行映像,设置新的ssl会话,使底层套接字无阻塞,然后将filedescriptor添加到select / poll / epoll循环中。
如果客户端发送数据,主循环将把它发送到ssl_read。如果返回SSL_ERROR_WANT_READ或SSL_ERROR_WANT_WRITE,必须在此处执行什么操作? WANT_READ可能很简单,因为下一个主循环迭代可能只会导致另一个ssl_read。但是如果ssl_read返回WANT_WRITE,应该调用哪些参数?为什么库本身不发出呼叫?
如果服务器想要向客户端发送一些数据,它将使用ssl_write。同样,如果返回WANT_READ或WANT_WRITE,该怎么办?可以通过重复刚刚调用的同一个调用来回答WANT_WRITE吗?如果返回WANT_READ,是否应该返回主循环并让select / poll / epoll处理这个问题?但是首先应该写的信息呢?
或者在写入失败后是否应该立即完成读取?那么,当真正的解析器位于主循环中时,什么可以防止从应用程序协议中读取字节,然后在应用程序的郊区某处处理它?</ p>
答案 0 :(得分:47)
对于非阻塞套接字,SSL_WANT_READ
表示“等待套接字可读,然后再次调用此函数。”;相反,SSL_WANT_WRITE
表示“等待套接字可写,然后再次调用此函数。”。您可以通过SSL_WANT_WRITE
或SSL_WANT_READ
来电获得SSL_read()
或SSL_write()
。
答案 1 :(得分:14)
您是否已阅读ssl_read和ssl_get_error的OpenSSL文档?
ssl_read:
如果底层BIO阻塞, SSL_read()只会返回一次 读取操作已完成或已完成 发生错误,除了a 重新谈判发生在其中 情况可能会发生SSL_ERROR_WANT_READ。 可以使用控制此行为 SSL_MODE_AUTO_RETRY标志 SSL_CTX_set_mode(3)调用。
如果底层BIO是非阻塞的, SSL_read()也会在返回时返回 潜在的BIO无法满足 需要SSL_read()来继续 操作。在这种情况下打电话给 SSL_get_error(3)带有返回值 SSL_read()将产生 SSL_ERROR_WANT_READ或 SSL_ERROR_WANT_WRITE。随时随地 可以重新谈判,打电话给 SSL_read()也可以导致写入 操作!然后调用过程 服用后必须重复打电话 适当的行动来满足 需要SSL_read()。那个行动 取决于潜在的BIO。什么时候 使用非阻塞套接字,什么都没有 要完成,但select()可以 用来检查所需的 条件。
ssl_get_error:
SSL_ERROR_WANT_READ,SSL_ERROR_WANT_WRITE
手术未完成;该 应该是相同的TLS / SSL I / O功能 稍后再打电话。那么,到那时, 底层BIO有可用的数据 阅读(如果结果代码是 SSL_ERROR_WANT_READ)或允许写入 数据(SSL_ERROR_WANT_WRITE),然后一些 将采用TLS / SSL协议进度 地方,即TLS / SSL的至少一部分 记录将被读取或写入。注意 重试可能再次导致a SSL_ERROR_WANT_READ或SSL_ERROR_WANT_WRITE 条件。没有固定的上限 对于可能的迭代次数 是必要的,直到进展成为 在应用程序协议级别可见。
对于套接字BIO(例如,当SSL_set_fd()时 用过),select()或者poll()就可以了 底层套接字可用于查找 在TLS / SSL I / O功能时输出 应该重试。
警告:任何TLS / SSL I / O功能都可以 导致SSL_ERROR_WANT_READ中的任何一个 和SSL_ERROR_WANT_WRITE。特别是, SSL_read()或SSL_peek()可能想要 写数据和SSL_write()可能想要 读数据。这主要是因为 任何时候都可能发生TLS / SSL握手 协议期间的时间(由协议发起) 客户端或服务器); SSL_read(),SSL_peek()和SSL_write() 将处理任何未决的握手。
OpenSSL是作为状态机实现的。 SSL_ERROR_WANT_READ
表示更多入站数据,SSL_ERROR_WANT_WRITE
表示需要更多出站数据才能在连接上取得进展。如果在ssl_read()操作上获得SSL_ERROR_WANT_WRITE
,则需要发送出站数据,或者至少等待套接字变为可写。如果在ssl_write()操作上获得SSL_ERROR_WANT_READ
,则需要读取入站数据。
您应订阅OpenSSL mailing lists。这个问题很多人被问到了。
答案 2 :(得分:5)
SSL_WANT_READ表示SSL引擎当前无法为您加密,因为它正在等待更多输入数据(作为初始握手的一部分或作为重新协商的一部分),因此,一旦您的下一次读取完成并且您' ve推送通过SSL引擎到达的数据,您可以重试您的写入操作。
同样,SSL_WANT_WRITE意味着SSL引擎正在等待您从中提取一些数据并将其发送给对等方。
我在2002年为Windows Developer Journal(重印here)撰写了关于使用OpenSSL和非阻塞和异步套接字的文章,虽然本文表面上针对的是Windows代码,但其他平台的主体是相同的。本文附带了一些代码,这些代码在Windows上将OpenSSL与异步套接字集成,并处理整个SSL_WANT_READ / SSL_WANT_WRITE问题。
基本上,当您获得SSL_WANT_READ时,您需要将出站数据排队,直到您完成读取并且已将新的入站数据传递到SSL引擎,一旦发生这种情况,您可以重试发送出站数据。