myio_apr.c

最終更新:2009/11/14

myio_apr.c

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: }
Copyright (C) KAKU PROJECT (2009)KAKU PROJECT (2009)