/* * ストリームの抽象化の試み * ・apr_file_t へのラッパー * ・apr_socket_t へのラッパー */ #include "myio_apr.h" /* * apr_file_t へのラッパーメソッド定義 */ #define MYIO_METHOD_NAME_FILE "APR_FILE_STREAM" typedef struct myio_fp_ctx { apr_file_t *fp; apr_pool_t *pool; } myio_fp_ctx; /* * size バイト分のデータを読み出す関数。 * 返り値は buf に読み出したバイト数。 * エラー時には -1 が返る。 */ int myio_read_fp( MYIO *in , char *buf , int size ) { apr_status_t rv = APR_SUCCESS; apr_size_t nbytes = size; myio_fp_ctx *ctx = (myio_fp_ctx*)(in->ptr); if (!ctx || ! ctx->fp) { return -1; } rv = apr_file_read(ctx->fp, buf, &nbytes); if (rv != APR_SUCCESS) { return -1; } return nbytes; } /* * buf に格納された size バイト分のデータを書き込む関数。 * 返り値は書き出したバイト数。 * エラー時には -1 が返る。 */ int myio_write_fp ( MYIO *out , const char *buf , int size ) { apr_status_t rv = APR_SUCCESS; apr_size_t nbytes = size; myio_fp_ctx *ctx = (myio_fp_ctx*)(out->ptr); if (!ctx || ! ctx->fp) { return -1; } rv = apr_file_write(ctx->fp, buf, &nbytes); if (rv != APR_SUCCESS) { return -1; } return nbytes; } /* * 文字列 str (ヌル文字で終端されたデータ)を書き込む関数。 * 返り値は書き出した文字列の長さ。 * エラー時には -1 が返る。 */ int myio_puts_fp ( MYIO *out , const char *str ) { apr_status_t rv = APR_SUCCESS; myio_fp_ctx *ctx = (myio_fp_ctx*)(out->ptr); if(0)printf("myio_puts_fp\n"); if (!ctx || ! ctx->fp) { return -1; } rv = apr_file_puts(str, ctx->fp); if (rv != APR_SUCCESS) { return -1; } return strlen(str); } /* * size-1 バイトまでの文字列をストリームから読み出し、buf に保存する。 * EOF または LF を読み込んだところで停止する。 * LF または CRLF は '\0' に書き換えられる。 * 返り値は最後のヌル文字を含まない読み出した文字列の長さ。 * エラー時には -1 が返る。 */ int myio_gets_fp ( MYIO *in , char *buf , int size ) { apr_status_t rv = APR_SUCCESS; int len = 0; myio_fp_ctx *ctx = (myio_fp_ctx*)(in->ptr); if(0)printf("myio_gets_fp\n"); if (!ctx || ! ctx->fp) { return -1; } rv = apr_file_gets(buf, size, ctx->fp); if (rv != APR_SUCCESS) { return -1; } { int i=0; len = strlen(buf); for (i=len-1; i>=0; i--) { if (buf[i] == MYIO_CHAR_LF || buf[i] == MYIO_CHAR_CR) { buf[i] = '\0'; } else { break; } } } return strlen(buf); } MYIO_METHOD myio_method_fp = { MYIO_METHOD_NAME_FILE , myio_write_fp , myio_read_fp , myio_puts_fp , myio_gets_fp }; apr_file_t *MYIO_fp_get_fp ( MYIO *myio ) { if (myio) { if (myio->method) { if (!strcmp(myio->method->name, MYIO_METHOD_NAME_FILE)) { myio_fp_ctx *ctx = (myio_fp_ctx *)(myio->ptr); return ctx->fp; } } } return NULL; } MYIO *MYIO_fp_new ( apr_file_t *fp , int flag /* フラグ。0:入力ストリーム、1:出力ストリーム*/ , apr_pool_t *pool ) { myio_fp_ctx *ctx = NULL; MYIO *myio = NULL; if (!fp || !pool) { return NULL; } ctx = (myio_fp_ctx*)apr_palloc(pool, sizeof(myio_fp_ctx)); if (!ctx) { return NULL; } ctx->fp = fp; ctx->pool = pool; myio = (MYIO*)apr_palloc(pool, sizeof(MYIO)); if (!myio) { return NULL; } return MYIO_make(myio, &myio_method_fp, (flag)?0:1, (flag)?1:0, ctx); } MYIO *MYIO_fp_open ( const char * fname , apr_int32_t flag , apr_fileperms_t perm , apr_pool_t *pool ) { apr_status_t rv = APR_SUCCESS; apr_file_t *fp = NULL; if (!fname || !pool) { return NULL; } rv = apr_file_open(&fp, fname, flag, perm, pool); if (rv != APR_SUCCESS) { return NULL; } return MYIO_fp_new(fp, (flag & APR_FOPEN_READ)?0:1, pool); } void MYIO_fp_close ( MYIO *myio ) { if (myio) { if (myio->method) { if (!strcmp(myio->method->name, MYIO_METHOD_NAME_FILE)) { myio_fp_ctx *ctx = (myio_fp_ctx *)(myio->ptr); if (ctx) { if (ctx->fp) { apr_file_close(ctx->fp); ctx->fp = NULL; } } myio->ptr = NULL; } } } } /* * apr_socket_t へのラッパーメソッド定義 */ #define MYIO_METHOD_NAME_SOCKET "APR_SOCKET_STREAM" typedef struct myio_sock_ctx_st { apr_socket_t *sock; apr_pool_t *pool; } myio_sock_ctx; /* * size バイト分のデータを読み出す関数。 * 返り値は buf に読み出したバイト数。 * エラー時には -1 が返る。 */ int myio_read_sock ( MYIO *in , char *buf , int size ) { apr_status_t rv = APR_SUCCESS; apr_size_t nbytes = size; myio_sock_ctx *ctx = (myio_sock_ctx*)(in->ptr); if (!ctx || ! ctx->sock) { return -1; } rv = apr_socket_recv(ctx->sock, buf, &nbytes); if (rv != APR_SUCCESS) { return -1; } return nbytes; } /* * buf に格納された size バイト分のデータを書き込む関数。 * 返り値は書き出したバイト数。 * エラー時には -1 が返る。 */ int myio_write_sock ( MYIO *out , const char *buf , int size ) { apr_status_t rv = APR_SUCCESS; apr_size_t nbytes = size; myio_sock_ctx *ctx = (myio_sock_ctx*)(out->ptr); if (!ctx || ! ctx->sock) { return -1; } rv = apr_socket_send(ctx->sock, buf, &nbytes); if (rv != APR_SUCCESS) { return -1; } return nbytes; } /* * 文字列 str (ヌル文字で終端されたデータ)を書き込む関数。 * 返り値は書き出した文字列の長さ。 * エラー時には -1 が返る。 */ int myio_puts_sock ( MYIO *out , const char *str ) { apr_status_t rv = APR_SUCCESS; myio_sock_ctx *ctx = (myio_sock_ctx*)(out->ptr); int size = 0; if (!ctx || ! ctx->sock) { return -1; } size = strlen(str); { int o=0; while (osock, str+o, &len); if (rv != APR_SUCCESS) { return -1; } o += len; } } return size; } MYIO_METHOD myio_method_sock = { MYIO_METHOD_NAME_SOCKET , myio_write_sock , myio_read_sock , myio_puts_sock , NULL /* 実装なし*/ }; apr_socket_t *MYIO_sock_get_sock ( MYIO *myio ) { if (myio) { if (myio->method) { if (!strcmp(myio->method->name, MYIO_METHOD_NAME_SOCKET)) { myio_sock_ctx *ctx = (myio_sock_ctx *)(myio->ptr); return ctx->sock; } } } return NULL; } MYIO *MYIO_sock_new ( apr_socket_t *sock , apr_pool_t *pool ) { myio_sock_ctx *ctx = NULL; MYIO *myio = NULL; if (!sock || !pool) { return NULL; } ctx = (myio_sock_ctx*)apr_palloc(pool, sizeof(myio_sock_ctx)); if (!ctx) { return NULL; } ctx->sock = sock; ctx->pool = pool; myio = (MYIO*)apr_palloc(pool, sizeof(MYIO)); if (!myio) { return NULL; } return MYIO_make(myio, &myio_method_sock, 1, 1, ctx); /* 双方向 */ } /* * 簡易ソケット接続関数 */ apr_socket_t *my_connect ( char *hostname , int port , apr_pool_t * pool ) { apr_socket_t *s = NULL; if (! pool || ! hostname || port<=0) { return NULL; } else { apr_status_t rv = APR_SUCCESS; apr_sockaddr_t *sa=NULL; rv = apr_sockaddr_info_get(&sa, hostname, APR_UNSPEC, port, 0, pool); if (APR_SUCCESS != rv) { return NULL; } for (; sa!=NULL; sa=sa->next) { rv = apr_socket_create(&s, sa->family, SOCK_STREAM, APR_PROTO_TCP, pool); if (APR_SUCCESS != rv) { continue; } rv = apr_socket_connect(s, sa); if (APR_SUCCESS == rv) { break; } } if (!sa) { return NULL; } } return s; } /* * ソケット接続し、MYIO オブジェクトを生成する関数 * 返り値: * 失敗時:ヌル * メモ: * ソケットオプションはデフォルト設定。 */ MYIO *MYIO_sock_connect( char *hostname /* 接続先ホスト名 */ , int port /* 接続先ポート番号 */ , apr_pool_t * pool ) { apr_socket_t *sock = my_connect (hostname, port, pool); if (!sock) { return NULL; } return MYIO_sock_new(sock, pool); } void MYIO_sock_close(MYIO *myio) { if (myio) { if (myio->method) { if (!strcmp(myio->method->name, MYIO_METHOD_NAME_SOCKET)) { myio_sock_ctx *ctx = (myio_sock_ctx *)(myio->ptr); if (ctx) { if (ctx->sock) { apr_socket_close(ctx->sock); ctx->sock = NULL; } myio->ptr = NULL; } } } } } int MYIO_apr_printf(MYIO *myio, const char *fmt, ...) { apr_pool_t *pool = NULL; if (myio) { if (myio->method) { if (!strcmp(myio->method->name, MYIO_METHOD_NAME_SOCKET)) { myio_sock_ctx *ctx = (myio_sock_ctx *)(myio->ptr); if (ctx) { if (ctx->pool) { pool = ctx->pool; } } } else if (!strcmp(myio->method->name, MYIO_METHOD_NAME_FILE)) { myio_fp_ctx *ctx = (myio_fp_ctx *)(myio->ptr); if (ctx) { if (ctx->pool) { pool = ctx->pool; } } } if (pool) { char *buf = NULL; va_list args; va_start(args, fmt); buf = apr_pvsprintf (pool, fmt, args); if (buf) { return myio->method->write(myio, buf, strlen(buf)); } } } } return -1; }