04WebServer Installer (v1.92) | 2011-09-04 00:12 |
04WebServer without Installer (v1.92) | 2011-09-04 00:10 |
04WebServer 1.xx では、ブロッキングモードのソケットを通信に使用していた。 マルチスレッド環境では、通信関数でスレッドをブロックさせればよく、selectを使う必要が無いので、転送効率は良い。
04WebServer 2.0 の通信では、以下の機能の実装を必要とした。
同等の機能は、1.xxでも実装されていたが、別のスレッドからclosesocketを呼ぶなど、良い実装とは言えなかった為、以下のように実装を変更した。
当初、WSAEventSelectと非同期I/Oで実現していたが、転送効率が悪かったため、オーバーラップI/Oへ変更した。 これにより、OpenSSLの利用も、独自BIOを使用したものに変更した。
独自BIOは、以下のように実装
/*! COverlappedSocket を入出力に使うBIO 参考:bss_file.c, bss_sock.c */ #include "StdAfx.h" #include "openssl/bio.h" #include "openssl/err.h" #include "OverlappedSocket.h" #define BIO_TYPE_OVR_SOCKET (30 | 0x400) // BIO_TYPE_SOURCE_SINK #ifndef MS_CALLBACK #define MS_CALLBACK #endif static int MS_CALLBACK ovrs_write(BIO *h, const char *buf, int num); static int MS_CALLBACK ovrs_read(BIO *h, char *buf, int size); static int MS_CALLBACK ovrs_puts(BIO *h, const char *str); static long MS_CALLBACK ovrs_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int MS_CALLBACK ovrs_new(BIO *h); static int MS_CALLBACK ovrs_free(BIO *data); static BIO_METHOD methods_ovrs = { BIO_TYPE_OVR_SOCKET, "COverlappedSocket", ovrs_write, ovrs_read, ovrs_puts, NULL, // ovr_gets, ovrs_ctrl, ovrs_new, ovrs_free, NULL, }; /*! インタフェース取得 */ BIO_METHOD *BIO_s_ovrs(void) { return(&methods_ovrs); } /*! 割り当て */ BIO *BIO_new_ovrs(COverlappedSocket *ovrs) { if(ovrs == NULL) return(NULL); // 新規生成 BIO *ret = BIO_new(BIO_s_ovrs()); if(ret == NULL) return(NULL); // 設定 ret->ptr = ovrs; ret->init = 1; return(ret); } /*! 初期化 */ static int ovrs_new(BIO *bi) { bi->init=0; bi->num=0; bi->ptr=NULL; bi->flags=0; return(1); } /*! 開放 */ static int ovrs_free(BIO *a) { if (a == NULL) return(0); a->ptr=NULL; a->init=0; return(1); } /*! 読み込み */ static int ovrs_read(BIO *b, char *out, int outl) { if(out != NULL) { // ポインタ取得 COverlappedSocket *ovrs = (COverlappedSocket*)b->ptr; // 操作実行 return(ovrs->BlockingRecv(out, outl)); } return(0); } /*! 書き込み */ static int ovrs_write(BIO *b, const char *in, int inl) { // ポインタ取得 COverlappedSocket *ovrs = (COverlappedSocket*)b->ptr; // 操作実行 return(ovrs->BlockingSend(const_cast<char *>(in), inl)); } /*! 書き込み(文字列) */ static int ovrs_puts(BIO *bp, const char *str) { return(ovrs_write(bp,str, strlen(str))); } /*! コントロール */ static long ovrs_ctrl(BIO *b, int cmd, long num, void *ptr) { long ret=1; switch (cmd) { case BIO_CTRL_RESET: num=0; case BIO_C_FILE_SEEK: ret=0; break; case BIO_CTRL_DUP: case BIO_CTRL_FLUSH: ret=1; break; default: ret=0; break; } return(ret); }