一連のプロトコル(redis、httpなど)を実装するTCPネットワークライブラリがあり、それらはBSDソケットを使用して実装されています。
多くのコードは、BSDソケット用のselect()やその他の関数を使用しています。これはSSLソケットでは機能しないと思いますか?それともそのまま動作しますか?
SSLソケットとBSDソケットが非常に異なるため、実装にまったく異なるアプローチが必要になるのではないかと思っています。
OpenSSLを参照していると仮定すると、OpenSSLはソケットの上にあり、それを置き換えるものではありません。したがって、のようなすべてのダイレクトソケット操作はselect()
引き続き機能します。ただし、違いは、OpenSSLが読み取りと書き込みを処理するため、に置き換えrecv()
たりssl_read()
、に置き換えたりsend()
することですが、直接ssl_write()
使用することもできます(場合によっては使用する必要があります)select()
。ただし、いつでも呼び出すことはできません。OpenSSLから呼び出すように指示されるまで待つ必要があります。したがって、たとえば、select()
最初に呼び出してから、読みやすさを報告recv()
するときにのみ呼び出す読み取りループがある場合は、そのロジックを入れ替える必要があります。最初に呼び出してから、select()
または(に注意してください)のいずれかが返される場合にのみ()を呼び出します。ssl_read()
select
ssl_read()
SSL_ERROR_WANT_READ
SSL_ERROR_WANT_WRITE
ssl_read()
内部で書き込み操作を実行ssl_write()
でき、内部で読み取り操作を実行できます)。
頭に浮かぶことの1つは、SSL接続が実行されるfdで選択を実行するべきではないということです。これは、たとえば、ssl_readがブロックしている間にそこから読み取ることができると言う場合があるためです。これは、たとえばSSLがキーの再ネゴシエーションを実行し、アプリケーションデータが使用可能にならないことが原因です。それは落とし穴の1つです。
これは遅れるかもしれませんが、将来のユーザーへの良い参考になるかもしれません。URL http://developerweb.net/viewtopic.php?id=6824でselect()関数を使用することについての良いスレッドがあります。引用された一例は次のとおりです
int sslsock_handle_nbio (ssl, ret, totv)
void *ssl; /* -> the SSL info */
int ret; /* the SSL I/O function return value */
struct timeval *totv; /* -> timeout info, or NULL */
{
int sfd, i;
fd_set rset, wset;
sfd = SSL_get_fd (ssl);
i = SSL_get_error (ssl, ret);
if (i == SSL_ERROR_WANT_READ) {
do {
FD_ZERO (&rset);
FD_SET (sfd, &rset);
i = select (sfd + 1, &rset, NULL, NULL, totv);
} while ((i < 0) && (errno == EINTR));
if (i == 0) {
/* the select() timed out */
ret = -2;
errno = ETIMEDOUT;
} else {
/* either an error, or it's readable */
ret = i;
}
} else if (i == SSL_ERROR_WANT_WRITE) {
do {
FD_ZERO (&wset);
FD_SET (sfd, &wset);
i = select (sfd + 1, NULL, &wset, NULL, totv);
} while ((i < 0) && (errno == EINTR));
if (i == 0) {
/* the select() timed out */
ret = -2;
errno = ETIMEDOUT;
} else {
/* either an error, or it's writable */
ret = i;
}
}
/* else, leave "ret" alone, and return it as-is */
return (ret);
}
これは、SSL_read()
またはを実行した後のみSSL_write()
です。