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);
}