mysvr_stab.c
最終更新:2010/3/7
001: /* mysvr_stab.c 002: * サーバ用スタブ 003: */ 004: 005: #include "mysvr_stab.h" 006: 007: 008: /* サブスレッド用情報構造体 */ 009: 010: typedef struct _my_service_data_st { 011: apr_pool_t *pool; /* サブスレッド用メモリプール */ 012: apr_socket_t *socket; /* クライアントソケット */ 013: } my_service_data; 014: 015: /* スレッドテーブル */ 016: 017: static my_thread_table mtt; 018: 019: /* サーバ情報 */ 020: 021: static my_server_info my_svr_info; 022: 023: static void my_signal_handler (int x) { 024: apr_file_printf(my_svr_info.err, "signal = [%d]\n", x); 025: my_thread_table_clear (&mtt); 026: if (my_svr_info.socket) { 027: apr_socket_close(my_svr_info.socket); 028: my_svr_info.socket = NULL; 029: } 030: } 031: 032: static void* APR_THREAD_FUNC do_my_service ( 033: apr_thread_t *thread 034: , void *sdata 035: ) { 036: my_service_data *data = (my_service_data*)sdata; 037: 038: my_service_main(data->pool, data->socket, &my_svr_info); 039: 040: /* コネクション切断 */ 041: if (data->socket) { 042: apr_socket_close(data->socket); 043: data->socket = NULL; 044: } 045: 046: /* HTTP セッション用メモリプールの開放 */ 047: apr_pool_destroy(data->pool); 048: 049: apr_thread_exit(thread, APR_SUCCESS); /* 【必須】サブスレッドの終了 */ 050: return NULL; 051: } 052: 053: int apr_my_main ( 054: int ac, char **av 055: , apr_file_t * astdin 056: , apr_file_t * astdout 057: , apr_file_t * astderr 058: , apr_pool_t * pool 059: ) { 060: 061: apr_status_t rv=APR_SUCCESS; 062: int error_flag = 0; 063: 064: /* シグナル設定 */ 065: 066: 067: apr_signal(SIGINT, my_signal_handler); 068: 069: my_svr_info.hostname = NULL; 070: my_svr_info.ip_addr = NULL; 071: my_svr_info.port = -1; 072: my_svr_info.socket = NULL; 073: my_svr_info.timeout_sec = DEFAULT_TIMEOUT_SEC; 074: my_svr_info.num_threads = DEFAULT_NUM_THREADS; 075: 076: my_svr_info.out = astdout; 077: my_svr_info.in = astdin; 078: my_svr_info.err = astderr; 079: 080: my_svr_info.config = NULL; 081: 082: if (my_service_init(ac, av, &my_svr_info) == 0) { 083: error_flag = 1; 084: goto _FINALLY_; 085: } 086: 087: if (my_svr_info.port <= 0) { 088: apr_file_printf(astderr, "ERROR: port=[%d]\n", my_svr_info.port); 089: error_flag = 1; 090: goto _FINALLY_; 091: } 092: 093: if (my_svr_info.num_threads <= 0) { 094: apr_file_printf(astderr, "ERROR: num_threads=[%d]\n", 095: my_svr_info.num_threads); 096: error_flag = 1; 097: goto _FINALLY_; 098: } 099: 100: /* サーバソケットの用意〜リッスンまで */ 101: 102: { 103: apr_sockaddr_t *sa = NULL; 104: char *buf; 105: 106: rv = apr_sockaddr_info_get(&sa, my_svr_info.hostname, 107: /*APR_INET*/ APR_UNSPEC, my_svr_info.port, 0, pool); 108: if (APR_SUCCESS != rv) { 109: error_flag = 1; 110: goto _FINALLY_; 111: } 112: 113: rv = apr_sockaddr_ip_get (&buf, sa); 114: if (APR_SUCCESS != rv) { 115: error_flag = 1; 116: goto _FINALLY_; 117: } 118: my_svr_info.ip_addr = buf; 119: 120: rv = apr_socket_create(& my_svr_info.socket, sa->family, 121: SOCK_STREAM, APR_PROTO_TCP, pool); 122: if (APR_SUCCESS != rv) { 123: error_flag = 1; 124: goto _FINALLY_; 125: } 126: apr_socket_opt_set(my_svr_info.socket, APR_SO_NONBLOCK, 0); 127: apr_socket_timeout_set(my_svr_info.socket, -1); 128: apr_socket_opt_set(my_svr_info.socket, APR_SO_REUSEADDR, 1); 129: 130: rv = apr_socket_bind(my_svr_info.socket, sa); 131: if (APR_SUCCESS != rv) { 132: error_flag = 1; 133: goto _FINALLY_; 134: } 135: rv = apr_socket_listen(my_svr_info.socket, SOMAXCONN); 136: if (APR_SUCCESS != rv) { 137: error_flag = 1; 138: goto _FINALLY_; 139: } 140: } 141: 142: /* スレッドテーブルの初期化 */ 143: my_thread_table_init(&mtt, my_svr_info.num_threads, pool); 144: 145: /* ループ:コネクション受付〜処理〜コネクション切断 */ 146: 147: while(my_svr_info.socket) 148: { 149: apr_socket_t *client_socket = NULL; 150: my_service_data *data = NULL; 151: apr_pool_t *my_service_pool = NULL; 152: apr_thread_t *thread=NULL; 153: 154: /* コネクション受付(ここでクライアントからの接続待ちでブロックする) */ 155: rv = apr_socket_accept(&client_socket, my_svr_info.socket, pool); 156: if (APR_SUCCESS != rv) { 157: error_flag = 1; 158: break; 159: } 160: apr_socket_opt_set(client_socket, APR_SO_NONBLOCK, 0); 161: /* タイムアウト設定(マイクロ秒) */ 162: apr_socket_timeout_set(client_socket, my_svr_info.timeout_sec*1000000); 163: 164: /* サブスレッド用メモリプールの生成 */ 165: rv=apr_pool_create(&my_service_pool, NULL); 166: if (APR_SUCCESS != rv) { 167: error_flag = 1; 168: break; 169: } 170: 171: data = (my_service_data*)apr_palloc(my_service_pool, 172: sizeof(my_service_data)); 173: data->pool = my_service_pool; 174: data->socket = client_socket; 175: 176: /* サブスレッドの生成 */ 177: 178: rv = my_thread_create (&mtt, &thread, do_my_service, (void*)data); 179: 180: if (APR_SUCCESS != rv) { 181: error_flag = 1; 182: break; 183: } 184: } 185: 186: _FINALLY_: 187: 188: if (APR_SUCCESS != rv) { 189: char error_buf[80]; 190: apr_file_printf(astderr, "ERROR: %s\n", 191: apr_strerror(rv, error_buf, sizeof(error_buf))); 192: } 193: 194: my_thread_table_clear (&mtt); 195: 196: my_service_finally(error_flag, &my_svr_info); 197: 198: if (error_flag) { 199: apr_file_printf(astderr, "\nfailed!\n"); 200: } else { 201: apr_file_printf(astdout, "\ndone.\n"); 202: } 203: 204: return error_flag; 205: }
KAKU PROJECT (2009) |