openssl を使用して tls を実装しました。一部のデータを受信した後、サーバーから大きなデータをダウンロード中にSSL_ERROR_SYSCALL
エラーが発生しました。小さいファイルの場合、このエラーは発生せず、エラーなしでダウンロードできます。ERR_get_error() は、大きなファイルに対してゼロを示しています。
Linux および C++ フレームワークを使用しています。失敗の理由を見つけるには?失敗の原因は何ですか?ご提案をよろしくお願いします。
SSL_ERROR_SYSCALLは、基盤となるI / O(この場合はTCPである必要があります)で問題が発生したことを示します。だから、あなたはerrnoでチェックしてみることができます。
OpenSSLヘルプによると:
SSL_ERROR_SYSCALL
I/Oエラーが発生しました。OpenSSLエラーキューには、エラーに関する詳細情報が含まれている場合があります。エラーキューが空の場合(つまり、ERR_get_error()が0を返す場合)、retを使用してエラーの詳細を調べることができます。ret== 0の場合、プロトコルに違反するEOFが観察されました。ret == -1の場合、基礎となるBIOはI / Oエラーを報告しました(UnixシステムのソケットI / Oについては、errnoで詳細を確認してください)。
ソースコードを調べると、正確に何が起こったのかわからないときにSSL_get_error()
返されることがわかります。SSL_ERROR_SYSCALL
基本的に、「不明」の場合のデフォルトの戻りコードです。
たとえば、私の場合 (BIO でノンブロッキング IO を実行している場合):
int buf;
const int n = SSL_read(ssl, &buf, 0);
const int err = SSL_get_error(ssl, n);
const int st = ERR_get_error();
n
が 0 の場合は、ただの理由err
になります。SSL_ERROR_SYSCALL
ただしst
、実際のエラーがなかったことを示す 0 のままです。SSL_read
に 0 バイトが書き込まれたため、0 が返されましたbuf
。
errno
ただし、詳細については、呼び出し後に/の値を探してWSAGetLastError()
ください。
バッファ サイズ 0 で SSL_read() を呼び出しているかどうかを確認します。SSL_pending() を使用して次のような間違いを犯しました。
int waitForReadFd = nBuf < bufSize;
if (waitForReadFd)
FD_SET(fd, &rfds);
// ...
// select
int doReadFd = FD_ISSET(fd, &rfds) || SSL_pending(ssl);
if (doReadFd)
n = SSL_read(ssl, buf, bufSize - nBuf);
バッファnBuf == bufSize
サイズ 0 で SSL_read() が呼び出されると、errno == 0 で SSL_ERROR_SYSCALL が発生します。
doReadFd チェックを変更すると、この問題を回避できます。
int doReadFd = FD_ISSET(fd, &rfds) || nBuf < bufSize && SSL_pending(ssl);
Go アプリケーションでこのエラーが発生しました。Goから基礎となるopensslライブラリに接続するために、サードパーティのライブラリを使用していました。データの読み取り中に、サード パーティ ライブラリは、読み取るバッファー/データの長さを 32 ビットの C.int に変換していました。2GB 以上の大きなデータの場合、オーバーフローが発生し、負の値が C.SSL_read 関数に渡されます。その場合、SSL_ERROR_SYSCALL エラーが発生しました。