2017-10-01 59 views
1

SSL_readを使用してOpensslリンクソケットからデータを読み取ろうとしています。私はコマンドを送信し、実世界のサーバーからデータを受け取るクライアントモードでOpenssl操作を実行します。 1つのスレッドが接続、書き込み、閉じるのようなすべてのOpenssl操作を処理する2つのスレッドを使用しました。別のスレッドでSSL_readを実行します。 SSL_readを一度発行すると、データを正しく読み取ることができます。SSL_readブロックが無期限に

しかし、複数の接続、書き込み、終了シーケンスを実行しようとすると問題に遭遇しました。理想的には、クローズに応答してSSL_readを実行するスレッドを終了する必要があります。これは、次回の接続では新しいsslポインターを取得するため、古いsslポインターの読み取りを実行したくないためです。しかし、問題は私がSSL_readを行うときです、私はSSLバッファで利用可能なデータがあるまで固執しています。他のスレッドでSSL接続を閉じても、SSLポインタでブロックされます。

while(1) { 
    memset(sbuf, 0, sizeof(uint8_t) * TLS_READ_RCVBUF_MAX_LEN); 

    read_data_len = SSL_read(con, sbuf, TLS_READ_RCVBUF_MAX_LEN); 
    switch (SSL_get_error(con, read)) { 
     case SSL_ERROR_NONE: 
. 
. 
. 
} 

私はこの問題に対してすべての解決策を試しましたが、動作しませんでした。ほとんど私はSSLバッファにデータがあるかもしれないことを知らせるための表示を試みましたが、どれも適切な表示を返しません。

私が試した:

を - SSLバッファにデータがあるかどうかを知るために最初SSL_pending行います。しかし、これは常にゼロを返します。

- Opensslソケットを選択してゼロより大きい値を戻すかどうかを確認します。しかし、常にゼロを返します。

- ソケットを非ブロッキングにして選択を試みますが、動作しないようです。私はコードが適切かどうかわかりません。

ブロックソケットにselectを使用した例は、次のとおりです。しかし、selectは常にゼロを返します。あなたは私が閉じるように反応して終了することSSL_readを実行するスレッドを取得するためのいくつかの方法を試してみましたが、私は予想通り、私はそれが仕事を得るdidntは見ることができるように

while(1) { 
    // The use of Select here is to timeout 
    // while waiting for data to read on SSL. 
    // The timeout is set to 1 second 
    i = select(width, &readfds, NULL, 
      NULL, &tv); 
    if (i < 0) { 
     // Select Error. Take appropriate action for this error 
    } 

    // Check if there is data to be read 
    if (i > 0) { 
     if (FD_ISSET(SSL_get_fd(con), &readfds)) { 
      // TODO: We have data in the SSL buffer. But are we 
      //  sure that the data is from read buffer? If not, 
      //  SSL_read can be stuck indefinitely. 
      //  Maybe we can do SSL_read(con, sbuf, 0) followed 
      //  by SSL_pending to find out? 
      memset(sbuf, 0, sizeof(uint8_t) * TLS_READ_RCVBUF_MAX_LEN); 

      read_data_len = SSL_read(con, sbuf, TLS_READ_RCVBUF_MAX_LEN); 
      error = SSL_get_error(con, read_data_len); 
      switch (error) { 
. 
. 
} 

。誰かSSL_readが正しく動作するようになったのですか?私の問題は、ノンブロッキングソケットのみの解決策ですか?ブロッキングソケットの場合コマンドに対する応答が得られない場合、SSL_readからの終了の問題をどのように解決しますか?あなたは、読み取りと非ブロッキングソケットのための作業ソリューションの例を与えることができますか?

答えて

0

私はそれが(ポーリングイベントループに基づく)標準のLinux IOと、非ブロッキングソケットを使用しています... SSLと非ブロッククライアントソケットの実施例にhttps://github.com/darrenjs/openssl_examples

あなたを指すことができます。生データはソケットから読み取られ、SSLメモリBIOに送られ、その後、復号化が実行されます。

私が使用したアプローチはシングルスレッドでした。 1つのスレッドが接続、書き込み、および読み取りを実行します。これは、あるスレッドがソケットを閉じている間に別のスレッドがそのソケットを使用しようとしているときに問題が発生しないことを意味します。また、SSL FAQで指摘されているように、「SSL接続を複数のスレッドで同時に使用することはできません」(https://www.openssl.org/docs/faq.html#PROG1)ので、シングルスレッドのアプローチでは同時SSL書き込みの問題を回避します。&

シングルスレッドアプローチの課題は、アウトバウンド用に保留中のデータ(たとえば、クライアントからサーバーに送信するコマンド)を送信して保持するための何らかの種類の同期キュー&シグナリングメカニズムを作成する必要があることです。書き込みのために保留中のデータがあるかどうかを検出するソケットイベントループを取得し、キューなどからプルします。標準のstd :: list、std :: mutexなど、そしてイベントを通知するpipe2またはeventfdループ。

関連する問題