/* mysvr_stab.c * サーバ用スタブ */ #include "mysvr_stab.h" /* サブスレッド用情報構造体 */ typedef struct _my_service_data_st { apr_pool_t *pool; /* サブスレッド用メモリプール */ apr_socket_t *socket; /* クライアントソケット */ } my_service_data; /* スレッドテーブル */ static my_thread_table mtt; /* サーバ情報 */ static my_server_info my_svr_info; static void my_signal_handler (int x) { apr_file_printf(my_svr_info.err, "signal = [%d]\n", x); my_thread_table_clear (&mtt); if (my_svr_info.socket) { apr_socket_close(my_svr_info.socket); my_svr_info.socket = NULL; } } static void* APR_THREAD_FUNC do_my_service ( apr_thread_t *thread , void *sdata ) { my_service_data *data = (my_service_data*)sdata; my_service_main(data->pool, data->socket, &my_svr_info); /* コネクション切断 */ if (data->socket) { apr_socket_close(data->socket); data->socket = NULL; } /* HTTP セッション用メモリプールの開放 */ apr_pool_destroy(data->pool); apr_thread_exit(thread, APR_SUCCESS); /* 【必須】サブスレッドの終了 */ return NULL; } int apr_my_main ( int ac, char **av , apr_file_t * astdin , apr_file_t * astdout , apr_file_t * astderr , apr_pool_t * pool ) { apr_status_t rv=APR_SUCCESS; int error_flag = 0; /* シグナル設定 */ apr_signal(SIGINT, my_signal_handler); my_svr_info.hostname = NULL; my_svr_info.ip_addr = NULL; my_svr_info.port = -1; my_svr_info.socket = NULL; my_svr_info.timeout_sec = DEFAULT_TIMEOUT_SEC; my_svr_info.num_threads = DEFAULT_NUM_THREADS; my_svr_info.out = astdout; my_svr_info.in = astdin; my_svr_info.err = astderr; my_svr_info.config = NULL; if (my_service_init(ac, av, &my_svr_info) == 0) { error_flag = 1; goto _FINALLY_; } if (my_svr_info.port <= 0) { apr_file_printf(astderr, "ERROR: port=[%d]\n", my_svr_info.port); error_flag = 1; goto _FINALLY_; } if (my_svr_info.num_threads <= 0) { apr_file_printf(astderr, "ERROR: num_threads=[%d]\n", my_svr_info.num_threads); error_flag = 1; goto _FINALLY_; } /* サーバソケットの用意〜リッスンまで */ { apr_sockaddr_t *sa = NULL; char *buf; rv = apr_sockaddr_info_get(&sa, my_svr_info.hostname, /*APR_INET*/ APR_UNSPEC, my_svr_info.port, 0, pool); if (APR_SUCCESS != rv) { error_flag = 1; goto _FINALLY_; } rv = apr_sockaddr_ip_get (&buf, sa); if (APR_SUCCESS != rv) { error_flag = 1; goto _FINALLY_; } my_svr_info.ip_addr = buf; rv = apr_socket_create(& my_svr_info.socket, sa->family, SOCK_STREAM, APR_PROTO_TCP, pool); if (APR_SUCCESS != rv) { error_flag = 1; goto _FINALLY_; } apr_socket_opt_set(my_svr_info.socket, APR_SO_NONBLOCK, 0); apr_socket_timeout_set(my_svr_info.socket, -1); apr_socket_opt_set(my_svr_info.socket, APR_SO_REUSEADDR, 1); rv = apr_socket_bind(my_svr_info.socket, sa); if (APR_SUCCESS != rv) { error_flag = 1; goto _FINALLY_; } rv = apr_socket_listen(my_svr_info.socket, SOMAXCONN); if (APR_SUCCESS != rv) { error_flag = 1; goto _FINALLY_; } } /* スレッドテーブルの初期化 */ my_thread_table_init(&mtt, my_svr_info.num_threads, pool); /* ループ:コネクション受付〜処理〜コネクション切断 */ while(my_svr_info.socket) { apr_socket_t *client_socket = NULL; my_service_data *data = NULL; apr_pool_t *my_service_pool = NULL; apr_thread_t *thread=NULL; /* コネクション受付(ここでクライアントからの接続待ちでブロックする) */ rv = apr_socket_accept(&client_socket, my_svr_info.socket, pool); if (APR_SUCCESS != rv) { error_flag = 1; break; } apr_socket_opt_set(client_socket, APR_SO_NONBLOCK, 0); /* タイムアウト設定(マイクロ秒) */ apr_socket_timeout_set(client_socket, my_svr_info.timeout_sec*1000000); /* サブスレッド用メモリプールの生成 */ rv=apr_pool_create(&my_service_pool, NULL); if (APR_SUCCESS != rv) { error_flag = 1; break; } data = (my_service_data*)apr_palloc(my_service_pool, sizeof(my_service_data)); data->pool = my_service_pool; data->socket = client_socket; /* サブスレッドの生成 */ rv = my_thread_create (&mtt, &thread, do_my_service, (void*)data); if (APR_SUCCESS != rv) { error_flag = 1; break; } } _FINALLY_: if (APR_SUCCESS != rv) { char error_buf[80]; apr_file_printf(astderr, "ERROR: %s\n", apr_strerror(rv, error_buf, sizeof(error_buf))); } my_thread_table_clear (&mtt); my_service_finally(error_flag, &my_svr_info); if (error_flag) { apr_file_printf(astderr, "\nfailed!\n"); } else { apr_file_printf(astdout, "\ndone.\n"); } return error_flag; }