mysvr_stab.c

最終更新:2010/3/7

mysvr_stab.c

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