epoll版 stone のバグを長いこと放置していた... orz
(1) getident
(2) SSL_connect に時間がかかる場合の挙動
(1) のバグは、sd = socket() するまえに epoll_ctl(epfd, EPOLL_CTL_ADD, sd, &ev) していた、という単純バグ。なぜ epoll_ctl が失敗しなかったというと sd を初期化していなかったので、たまたま有効なディスクリプタだったのだろう。これは順序を入れ替えるだけで fix.
(2) は、少し複雑。stone は中継先に connect する際、どのタイミングで接続が確立するかで処理のパスが変わる。たとえば connect が EINPROGRESS を返すと epoll/select 待ちするが、connect を呼び出した時点で接続が確立すれば、直接 readWrite ループへ遷移する。
SSL がからむともっと複雑になる。SSL_accept が完了するまで中継先が決まらない場合もあるし、TCP接続が確立しても SSL接続がなかなか確立しない場合もある。SSLハンドシェークに時間がかかる場合、SSL_accept / SSL_connect は readWrite ループで呼び出されることになる。
SSL_connect が完了する前に中継元からの入出力が行われてはまずいので、readWrite ループ内の epoll/select 待ちでは中継元側のディスクリプタは監視対象からはずしているわけだが、SSL_connect が成功した時点で監視対象に含めなければならない。select 版では正常に動作するのだが、epoll 版では監視対象に含め損なっていた。
ret = SSL_connect(ssl); if (ret > 0) { /* success */ + Pair *p = pair->pair; /* pair & dst is connected */ pair->proto |= (proto_connect | proto_dirty); + if (p) p->proto |= proto_dirty; /* src */
接続元側 Pair の proto に、proto_dirty フラグを設定することにより、epoll でも監視対象に含めるようになる。
これで epoll 版も正常に動くようになったはず。
現在 senri で動作検証中...
$Id: stone.c,v 2.2.2.20 2006/04/28 21:50:24 hiroaki_sengoku Exp $