myio_apr.c
最終更新:2009/11/14
001: /*
002: * ストリームの抽象化の試み
003: * ・apr_file_t へのラッパー
004: * ・apr_socket_t へのラッパー
005: */
006:
007: #include "myio_apr.h"
008:
009: /*
010: * apr_file_t へのラッパーメソッド定義
011: */
012:
013: #define MYIO_METHOD_NAME_FILE "APR_FILE_STREAM"
014:
015: typedef struct myio_fp_ctx {
016: apr_file_t *fp;
017: apr_pool_t *pool;
018: } myio_fp_ctx;
019:
020: /*
021: * size バイト分のデータを読み出す関数。
022: * 返り値は buf に読み出したバイト数。
023: * エラー時には -1 が返る。
024: */
025:
026: int myio_read_fp(
027: MYIO *in
028: , char *buf
029: , int size
030: ) {
031: apr_status_t rv = APR_SUCCESS;
032: apr_size_t nbytes = size;
033: myio_fp_ctx *ctx = (myio_fp_ctx*)(in->ptr);
034: if (!ctx || ! ctx->fp) {
035: return -1;
036: }
037: rv = apr_file_read(ctx->fp, buf, &nbytes);
038: if (rv != APR_SUCCESS) {
039: return -1;
040: }
041: return nbytes;
042: }
043:
044: /*
045: * buf に格納された size バイト分のデータを書き込む関数。
046: * 返り値は書き出したバイト数。
047: * エラー時には -1 が返る。
048: */
049:
050: int myio_write_fp (
051: MYIO *out
052: , const char *buf
053: , int size
054: ) {
055: apr_status_t rv = APR_SUCCESS;
056: apr_size_t nbytes = size;
057: myio_fp_ctx *ctx = (myio_fp_ctx*)(out->ptr);
058: if (!ctx || ! ctx->fp) {
059: return -1;
060: }
061: rv = apr_file_write(ctx->fp, buf, &nbytes);
062: if (rv != APR_SUCCESS) {
063: return -1;
064: }
065: return nbytes;
066: }
067:
068: /*
069: * 文字列 str (ヌル文字で終端されたデータ)を書き込む関数。
070: * 返り値は書き出した文字列の長さ。
071: * エラー時には -1 が返る。
072: */
073:
074: int myio_puts_fp (
075: MYIO *out
076: , const char *str
077: ) {
078: apr_status_t rv = APR_SUCCESS;
079: myio_fp_ctx *ctx = (myio_fp_ctx*)(out->ptr);
080: if(0)printf("myio_puts_fp\n");
081: if (!ctx || ! ctx->fp) {
082: return -1;
083: }
084: rv = apr_file_puts(str, ctx->fp);
085: if (rv != APR_SUCCESS) {
086: return -1;
087: }
088: return strlen(str);
089: }
090:
091: /*
092: * size-1 バイトまでの文字列をストリームから読み出し、buf に保存する。
093: * EOF または LF を読み込んだところで停止する。
094: * LF または CRLF は '\0' に書き換えられる。
095: * 返り値は最後のヌル文字を含まない読み出した文字列の長さ。
096: * エラー時には -1 が返る。
097: */
098: int myio_gets_fp (
099: MYIO *in
100: , char *buf
101: , int size
102: ) {
103: apr_status_t rv = APR_SUCCESS;
104: int len = 0;
105: myio_fp_ctx *ctx = (myio_fp_ctx*)(in->ptr);
106: if(0)printf("myio_gets_fp\n");
107: if (!ctx || ! ctx->fp) {
108: return -1;
109: }
110: rv = apr_file_gets(buf, size, ctx->fp);
111: if (rv != APR_SUCCESS) {
112: return -1;
113: }
114: {
115: int i=0;
116: len = strlen(buf);
117: for (i=len-1; i>=0; i--) {
118: if (buf[i] == MYIO_CHAR_LF || buf[i] == MYIO_CHAR_CR) {
119: buf[i] = '\0';
120: } else {
121: break;
122: }
123: }
124: }
125: return strlen(buf);
126: }
127:
128: MYIO_METHOD myio_method_fp = {
129: MYIO_METHOD_NAME_FILE
130: , myio_write_fp
131: , myio_read_fp
132: , myio_puts_fp
133: , myio_gets_fp
134: };
135:
136: apr_file_t *MYIO_fp_get_fp (
137: MYIO *myio
138: ) {
139: if (myio) {
140: if (myio->method) {
141: if (!strcmp(myio->method->name, MYIO_METHOD_NAME_FILE)) {
142: myio_fp_ctx *ctx = (myio_fp_ctx *)(myio->ptr);
143: return ctx->fp;
144: }
145: }
146: }
147: return NULL;
148: }
149:
150: MYIO *MYIO_fp_new (
151: apr_file_t *fp
152: , int flag /* フラグ。0:入力ストリーム、1:出力ストリーム*/
153: , apr_pool_t *pool
154: ) {
155: myio_fp_ctx *ctx = NULL;
156: MYIO *myio = NULL;
157: if (!fp || !pool) {
158: return NULL;
159: }
160: ctx = (myio_fp_ctx*)apr_palloc(pool, sizeof(myio_fp_ctx));
161: if (!ctx) {
162: return NULL;
163: }
164: ctx->fp = fp;
165: ctx->pool = pool;
166: myio = (MYIO*)apr_palloc(pool, sizeof(MYIO));
167: if (!myio) {
168: return NULL;
169: }
170:
171: return MYIO_make(myio, &myio_method_fp, (flag)?0:1, (flag)?1:0, ctx);
172: }
173:
174: MYIO *MYIO_fp_open (
175: const char * fname
176: , apr_int32_t flag
177: , apr_fileperms_t perm
178: , apr_pool_t *pool
179: ) {
180: apr_status_t rv = APR_SUCCESS;
181: apr_file_t *fp = NULL;
182: if (!fname || !pool) {
183: return NULL;
184: }
185: rv = apr_file_open(&fp, fname, flag, perm, pool);
186: if (rv != APR_SUCCESS) {
187: return NULL;
188: }
189:
190: return MYIO_fp_new(fp, (flag & APR_FOPEN_READ)?0:1, pool);
191: }
192:
193: void MYIO_fp_close (
194: MYIO *myio
195: ) {
196: if (myio) {
197: if (myio->method) {
198: if (!strcmp(myio->method->name, MYIO_METHOD_NAME_FILE)) {
199: myio_fp_ctx *ctx = (myio_fp_ctx *)(myio->ptr);
200: if (ctx) {
201: if (ctx->fp) {
202: apr_file_close(ctx->fp);
203: ctx->fp = NULL;
204: }
205: }
206: myio->ptr = NULL;
207: }
208: }
209: }
210: }
211:
212: /*
213: * apr_socket_t へのラッパーメソッド定義
214: */
215:
216: #define MYIO_METHOD_NAME_SOCKET "APR_SOCKET_STREAM"
217:
218: typedef struct myio_sock_ctx_st {
219: apr_socket_t *sock;
220: apr_pool_t *pool;
221: } myio_sock_ctx;
222:
223: /*
224: * size バイト分のデータを読み出す関数。
225: * 返り値は buf に読み出したバイト数。
226: * エラー時には -1 が返る。
227: */
228:
229: int myio_read_sock (
230: MYIO *in
231: , char *buf
232: , int size
233: ) {
234: apr_status_t rv = APR_SUCCESS;
235: apr_size_t nbytes = size;
236: myio_sock_ctx *ctx = (myio_sock_ctx*)(in->ptr);
237: if (!ctx || ! ctx->sock) {
238: return -1;
239: }
240: rv = apr_socket_recv(ctx->sock, buf, &nbytes);
241: if (rv != APR_SUCCESS) {
242: return -1;
243: }
244: return nbytes;
245: }
246:
247: /*
248: * buf に格納された size バイト分のデータを書き込む関数。
249: * 返り値は書き出したバイト数。
250: * エラー時には -1 が返る。
251: */
252:
253: int myio_write_sock (
254: MYIO *out
255: , const char *buf
256: , int size
257: ) {
258: apr_status_t rv = APR_SUCCESS;
259: apr_size_t nbytes = size;
260: myio_sock_ctx *ctx = (myio_sock_ctx*)(out->ptr);
261: if (!ctx || ! ctx->sock) {
262: return -1;
263: }
264: rv = apr_socket_send(ctx->sock, buf, &nbytes);
265: if (rv != APR_SUCCESS) {
266: return -1;
267: }
268: return nbytes;
269: }
270:
271: /*
272: * 文字列 str (ヌル文字で終端されたデータ)を書き込む関数。
273: * 返り値は書き出した文字列の長さ。
274: * エラー時には -1 が返る。
275: */
276:
277: int myio_puts_sock (
278: MYIO *out
279: , const char *str
280: ) {
281: apr_status_t rv = APR_SUCCESS;
282: myio_sock_ctx *ctx = (myio_sock_ctx*)(out->ptr);
283: int size = 0;
284:
285: if (!ctx || ! ctx->sock) {
286: return -1;
287: }
288:
289: size = strlen(str);
290:
291: {
292: int o=0;
293: while (o<size) {
294: apr_size_t len = size-o;
295: rv = apr_socket_send(ctx->sock, str+o, &len);
296: if (rv != APR_SUCCESS) {
297: return -1;
298: }
299: o += len;
300: }
301: }
302: return size;
303: }
304:
305: MYIO_METHOD myio_method_sock = {
306: MYIO_METHOD_NAME_SOCKET
307: , myio_write_sock
308: , myio_read_sock
309: , myio_puts_sock
310: , NULL /* 実装なし*/
311: };
312:
313: apr_socket_t *MYIO_sock_get_sock (
314: MYIO *myio
315: ) {
316: if (myio) {
317: if (myio->method) {
318: if (!strcmp(myio->method->name, MYIO_METHOD_NAME_SOCKET)) {
319: myio_sock_ctx *ctx = (myio_sock_ctx *)(myio->ptr);
320: return ctx->sock;
321: }
322: }
323: }
324: return NULL;
325: }
326:
327: MYIO *MYIO_sock_new (
328: apr_socket_t *sock
329: , apr_pool_t *pool
330: ) {
331: myio_sock_ctx *ctx = NULL;
332: MYIO *myio = NULL;
333: if (!sock || !pool) {
334: return NULL;
335: }
336: ctx = (myio_sock_ctx*)apr_palloc(pool, sizeof(myio_sock_ctx));
337: if (!ctx) {
338: return NULL;
339: }
340: ctx->sock = sock;
341: ctx->pool = pool;
342: myio = (MYIO*)apr_palloc(pool, sizeof(MYIO));
343: if (!myio) {
344: return NULL;
345: }
346:
347: return MYIO_make(myio, &myio_method_sock, 1, 1, ctx); /* 双方向 */
348: }
349: /*
350: * 簡易ソケット接続関数
351: */
352: apr_socket_t *my_connect (
353: char *hostname
354: , int port
355: , apr_pool_t * pool
356: ) {
357:
358: apr_socket_t *s = NULL;
359:
360: if (! pool || ! hostname || port<=0) {
361:
362: return NULL;
363:
364: } else {
365:
366: apr_status_t rv = APR_SUCCESS;
367: apr_sockaddr_t *sa=NULL;
368:
369: rv = apr_sockaddr_info_get(&sa, hostname, APR_UNSPEC, port, 0, pool);
370: if (APR_SUCCESS != rv) {
371: return NULL;
372: }
373:
374: for (; sa!=NULL; sa=sa->next)
375: {
376: rv = apr_socket_create(&s, sa->family,
377: SOCK_STREAM, APR_PROTO_TCP, pool);
378: if (APR_SUCCESS != rv) {
379: continue;
380: }
381:
382: rv = apr_socket_connect(s, sa);
383: if (APR_SUCCESS == rv) {
384: break;
385: }
386: }
387:
388: if (!sa) {
389: return NULL;
390: }
391: }
392:
393: return s;
394: }
395:
396: /*
397: * ソケット接続し、MYIO オブジェクトを生成する関数
398: * 返り値:
399: * 失敗時:ヌル
400: * メモ:
401: * ソケットオプションはデフォルト設定。
402: */
403:
404: MYIO *MYIO_sock_connect(
405: char *hostname /* 接続先ホスト名 */
406: , int port /* 接続先ポート番号 */
407: , apr_pool_t * pool
408: ) {
409: apr_socket_t *sock = my_connect (hostname, port, pool);
410: if (!sock) {
411: return NULL;
412: }
413:
414: return MYIO_sock_new(sock, pool);
415: }
416:
417: void MYIO_sock_close(MYIO *myio) {
418: if (myio) {
419: if (myio->method) {
420: if (!strcmp(myio->method->name, MYIO_METHOD_NAME_SOCKET)) {
421: myio_sock_ctx *ctx = (myio_sock_ctx *)(myio->ptr);
422: if (ctx) {
423: if (ctx->sock) {
424: apr_socket_close(ctx->sock);
425: ctx->sock = NULL;
426: }
427: myio->ptr = NULL;
428: }
429: }
430: }
431: }
432: }
433:
434: int MYIO_apr_printf(MYIO *myio, const char *fmt, ...) {
435: apr_pool_t *pool = NULL;
436: if (myio) {
437: if (myio->method) {
438: if (!strcmp(myio->method->name, MYIO_METHOD_NAME_SOCKET)) {
439: myio_sock_ctx *ctx = (myio_sock_ctx *)(myio->ptr);
440: if (ctx) {
441: if (ctx->pool) {
442: pool = ctx->pool;
443: }
444: }
445: } else if (!strcmp(myio->method->name, MYIO_METHOD_NAME_FILE)) {
446: myio_fp_ctx *ctx = (myio_fp_ctx *)(myio->ptr);
447: if (ctx) {
448: if (ctx->pool) {
449: pool = ctx->pool;
450: }
451: }
452: }
453: if (pool) {
454: char *buf = NULL;
455: va_list args;
456: va_start(args, fmt);
457: buf = apr_pvsprintf (pool, fmt, args);
458: if (buf) {
459: return myio->method->write(myio, buf, strlen(buf));
460: }
461: }
462: }
463: }
464: return -1;
465: }
![]() | KAKU PROJECT (2009) |