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) |