OpenSSLのFAQ
この仕様は、blocking IOの時に問題となる。SSL_read()でブロックしている最中に別スレッドからSSL_write()することができないのだ。
SSL上の通信が、Read,Writeがシーケンシャルに行われるような通信の場合には問題とならないが、ReadとWriteが独立して行われる通信の場合、blocking IOのSSLは使えないことになる。
AndroidのSSL部はOpenSSLを使っているが、この辺りがどうなっているのか(制限がそのままあるのか、回避されているのか)を調べてみた。
結論としては、AndroidのSSLはマルチスレッド対応している。以下、その説明。
SSLSocketの実装は、OpenSSLSocketImpl.javaにある。
SSLSocketからは、NativeCrypto.cppの関数が呼ばれている。
NativeCrypto.cppのNativeCrypto_SSL_do_handshake()で、ソケットをnon-blockingにしている。
/*
* Make socket non-blocking, so SSL_connect SSL_read() and SSL_write() don't hang
* forever and we can use select() to find out if the socket is ready.
*/
if (!setBlocking(fd.get(), false)) {
throwSSLExceptionStr(env, "Unable to make socket non blocking");
SSL_clear(ssl);
JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
return 0;
}
NativeCrypto.cppのsslRead()とsslWrite()には、以下のコメントがある。
/*
* Helper function which does the actual writing. The Java layer guarantees that
* at most one thread will enter this function at any given time.
関数の中身を見ると、
1. non-blockingでSSL_read()/SSL_write()を呼び出す。
2. 失敗した場合は、sslSelect()を呼び、ブロックする。
としている。
結局、
・AndroidのSSLは、non-blocking IOを使っているが、上位にはblockingのAPIを提供している。
・OpenSSLのblocking IOにあるような、マルチスレッドの呼び出し制限は無い。
ということで、ユーザーにとって使いやすいAPIとなっている。
0 件のコメント:
コメントを投稿