AcceptExとOpenSSLを使用してクライアントからの新しい接続を処理する適切な方法を知りたいです。私は、通常のHTTPを介してIO完了ポートでAcceptExを使用する完全に機能するサーバーを持っています。OpenSSLサポートを追加したいと思います。
ノンブロッキングソケットでのOpenSSLの使用に関するインターネット上のいくつかの記事を読みました。
- IO完了ポートとOpenSSL
- http://zzz.zggg.com/2007/12/22/ssl-server-with-openssl-memory-bio-aka-prerequisite-to-asynchronous-openssl/
- http://marc.info/?l=openssl-users&m=99909952822335&w=2
- http://www.lenholgate.com/blog/2002/11/using-openssl-with-asynchronous-sockets.html
彼らは主に接続のクライアント側に関係しているので、それらのどれもこれを行う方法に触れていないようです。AcceptExはソケット接続を確立し、クライアントから送信された最初のデータを返します。私が投稿した最初のリンクでは、IOCPを使用して受信データを処理する方法について説明しています。私はこれまで運がなかったのでそこに投稿されたものを試しました。基本的に、サーバーに表示されるのは次のとおりです。
- 受け入れられた接続完了が受信されます。
- SSL_new(ctx)を使用してSSLオブジェクトを作成します
- BIO_new(BIO_s_mem())を使用してインおよびアウトのBIOオブジェクトを作成します。
- SSL_set_bio(ssl、bioIn、bioOut)を呼び出して、SSLオブジェクトにBIOを設定します。
- SSL_set_accept_state(ssl)を呼び出して、SSL_readとSSL_writeがネゴシエーションを実行できるようにします。
次に、AcceptEx呼び出しによって読み取られたデータの最初のバッファーの処理を試みます。
- BIO_Write(bioIn、buf、len)を呼び出して、読み取ったデータをSSLにコピーします。
- 次に、bioOutで保留中のハンドシェイクデータをチェックして、それをクライアントに送り返す必要があるかどうかを確認します。新しい接続を受け入れるとき、私はこの時点でbioOutにデータがあるのを見たことがありません。
- 次に、SSL_read(ssl、plainTextBuf、len)を呼び出して、手順6でbioInに入れたデータを復号化しようとします。これは常に-1を返し、SSL_get_errorはERROR_SSL_WANT_READを返します。私が理解しているように、これはbioInが完全なSSLレコードを持っていないことを意味します。したがって、SSLは何かを復号化する前に、クライアントからのより多くのデータを必要とします。
ここで私は問題にぶつかり始めます、そしてそれは私が何らかの方向性を必要とすると思うところです。私は多くのことを試みました。この時点でSSL_readを繰り返し呼び出すと、ERROR_SSL_WANT_READが無限に返されます。これは、メモリを使用すると、BIOが実際にソケットを介して通信してデータを受信しないためと考えられます。クライアントからのより多くのデータを待つために、WSARecv呼び出しを投稿する必要がありますか?
また、この時点でBIO_readを使用してbioOutバッファーをチェックし、クライアントに送り返す必要のあるデータがあるかどうかを確認してみました。確かにいくつかあり、私はWSASendを使用してこれを送り返し、さらにデータを待つために別のWSARecv呼び出しを投稿します(私の送信に応答して)。これにより、クライアントからさらにデータを受信することになり(WSARecvは送信が完了した後に完了します)、接続が進行中であるように見えます。ただし、この完了した読み取りを処理すると、SSL_readとBIO_readの両方がERROR_SSL_WANT_READを返します。そのため、完全なレコードを復号化するのに十分なデータがなく、クライアントに送り返すものがありません。この状況に応じて別のWSARecv呼び出しを送信しても、クライアントからそれ以上のデータを受信することはありません。ここでSSLが何を求めているのかわかりません。
今は行き詰まっていますが、これからも頑張っていきます。何かわかったら、コメントでこの質問を更新します。