サーバにDLLはあまり使いたくなかったので、OpenSSLをスタティックライブラリとして組み込もうと考た。
インストール方法を見ると、makeファイルを変えるだけで良い模様。
で、NMakeを実行し、問題なくライブラリが出来る。
早速組み込んでみる。
Debugでコンパイル後、リンクでライブラリ競合の警告が出るが、まあ、動く模様。
しかし、Releaseでコンパイルすると・・・リンクエラーの嵐
どうやら、ライブラリの使っているランタイムライブラリと、実行ファイルの使っているランタイムライブラリが違うのが原因のようだ。
VC++には、以下の3(6)種類のランタイムライブラリがある。
で、OpenSSLは標準で/MDオプションでコンパイルされるため、04鯖のRelease(/MTオプション)と組み合わせると、リンクエラーになる模様。
OpenSSLを各オプションでコンパイルし直し、6種類のライブラリを使い分ける事で、問題は解決した。
しかし、昔全く同じ事で引っかかったような・・・
OpenSSLをマルチスレッドで利用するためには、二つのコールバック関数を登録する必要がある、と、FAQにあります。
要するに、排他処理を行うためのミューテックスを提供してやる必要があるわけですね。
OpenSSLのマニュアルは結構不親切ですが、マルチスレッドはテストコードがOpenSSLのソースにありますので、貰って来れば、まあ、さほど悩まなくとも実現できます。
FAQには二つとありますが、Win32環境では、ロック関数の登録のみで、スレッドID取得関数は必要ないようです。
HANDLE *g_lock_cs = NULL; void CSSLContext::InitLock() { if(g_lock_cs == NULL) { int i; g_lock_cs=(HANDLE*)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(HANDLE)); for (i=0; i<CRYPTO_num_locks(); i++) g_lock_cs[i]=CreateMutex(NULL,FALSE,NULL); CRYPTO_set_locking_callback(Locking_cb); } } void CSSLContext::Locking_cb(int mode, int type,const char *file, int line) { if (mode & CRYPTO_LOCK) WaitForSingleObject(g_lock_cs[type],INFINITE); else ReleaseMutex(g_lock_cs[type]); }
しかし、コードがあるんなら、標準でサポートしてくれてもいいような・・・
OpenSSLとは、各種暗号化ツールを詰め合わせたライブラリです。
04WebServerではSSLの実装に使われています。
OpenSSLを使って一番初めに詰まったのが、メモリリーク。
サンプルコードが、書籍やらネットやらに結構上がっているのですが、どれも漏れまくりです。
で、色々調べまわって見た結果、以下の事が分かりました。
全て実行しないとリークするようです。
何を実行する必要があるか、どこかにまとめておいて欲しかったなあ・・・
これをしないと、スレッドが終了するたびにメモリリークを起こします。
とりあえず、ERR_remove_state(0) は忘れがちになるんで、注意が必要です。
しかし、書籍のサンプルコードがメモリリークしまくりなのは・・・まあ、本自体は良い本でしたが。