/** * ソケット受信 * * @param[in] sock ソケット * @return ステータス */ static st_client read_sock(int sock) { int retval = 0; /* 戻り値 */ size_t length = 0; /* 送信または受信する長さ */ struct header hd; /* ヘッダ */ dbglog("start"); /* ヘッダ受信 */ length = sizeof(struct header); (void)memset(&hd, 0, length); retval = recv_data(sock, &hd, &length); if (retval < 0) /* エラー */ return EX_RECV_ERR; dbglog("recv_data: hd=%p, length=%zu", &hd, length); if (g_gflag) outdump(&hd, length, "recv: hd=%p, length=%zu", &hd, length); stddump(&hd, length, "recv: hd=%p, length=%zu", &hd, length); length = (size_t)ntohl((uint32_t)hd.length); /* データ長を保持 */ /* データ受信 */ answer = (unsigned char *)recv_data_new(sock, &length); if (!answer) /* メモリ確保できない */ return EX_ALLOC_ERR; if (!length) /* 受信エラー */ return EX_RECV_ERR; dbglog("answer=%p, length=%zu", answer, length); if (g_gflag) outdump(answer, length, "recv: answer=%p, length=%zu", answer, length); stddump(answer, length, "recv: answer=%p, length=%zu", answer, length); if (g_tflag) { unsigned int client_time = stop_timer(&start_time); print_timer(client_time); } retval = fprintf(stdout, "%s\n", answer); if (retval < 0) outlog("fprintf=%d", retval); memfree((void **)&answer, NULL); return EX_SUCCESS; }
/** * スレッド処理 * * @return なし */ static void * client_thread(void *arg) { /* スレッドデータ */ thread_data *dt = (thread_data *)arg; int retval = 0; /* 戻り値 */ size_t length = 0; /* 長さ */ ssize_t slen = 0; /* 送信するバイト数 */ struct header hd; /* ヘッダ */ /* コネクト */ dt->sock = connect_sock(); if (dt->sock < 0) { outstd("Connect error"); pthread_exit((void *)EX_CONNECT_ERR); } pthread_cleanup_push(thread_cleanup, &dt); length = strlen((char *)dt->expr) + 1; /* データ設定 */ slen = set_client_data(&dt->sdata, dt->expr, length); if (slen < 0) /* メモリ確保できない */ pthread_exit((void *)EX_ALLOC_ERR); pthread_cleanup_push(thread_memfree, &dt->sdata); /* データ送信 */ retval = send_data(dt->sock, dt->sdata, (size_t *)&slen); /* ヘッダ受信 */ length = sizeof(struct header); (void)memset(&hd, 0, length); retval = recv_data(dt->sock, &hd, &length); if (retval < 0) /* エラー */ pthread_exit((void *)EX_RECV_ERR); dbglog("recv_data: hd=%p, length=%zu", &hd, length); length = (size_t)ntohl((uint32_t)hd.length); /* データ長を保持 */ /* データ受信 */ dt->answer = (uchar *)recv_data_new(dt->sock, &length); if (!dt->answer) /* メモリ確保できない */ pthread_exit((void *)EX_ALLOC_ERR); pthread_cleanup_push(thread_memfree, &dt->answer); if (!length) /* 受信エラー */ pthread_exit((void *)EX_RECV_ERR); dbglog("answer=%p, length=%zu", dt->answer, length); stdlog("%s", dt->answer); retval = strcmp((char *)dt->expected, (char *)dt->answer); stdlog("strcmp=%d", retval); assert(0 == retval); retval = shutdown(dt->sock, SHUT_RDWR); if (retval < 0) { outstd("shutdown: sock=%d", dt->sock); pthread_exit((void *)EXIT_FAILURE); } pthread_cleanup_pop(1); pthread_cleanup_pop(1); pthread_cleanup_pop(1); pthread_exit((void *)EX_SUCCESS); return (void *)EX_SUCCESS; }
/** * サーバプロセス * * @param[in] arg ソケットディスクリプタ * @return 常にNULL */ static void * server_proc(void *arg) { thread_data dt; /* スレッドデータ構造体 */ int retval = 0; /* 戻り値 */ size_t length = 0; /* 長さ */ ssize_t slen = 0; /* 送信するバイト数 */ struct header hd; /* ヘッダ構造体 */ unsigned char *expr = NULL; /* 受信データ */ calcinfo calc; /* calc情報構造体 */ struct server_data *sdata = NULL; /* 送信データ構造体 */ (void)memcpy(&dt, arg, sizeof(thread_data)); dbglog("start: accept=%d sin_addr=%s sin_port=%d, len=%d", dt.sock, inet_ntoa(dt.addr.sin_addr), ntohs(dt.addr.sin_port), dt.len); /* シグナルマスクを設定 */ set_thread_sigmask(dt.sigmask); pthread_cleanup_push(thread_cleanup, &dt); do { /* ヘッダ受信 */ length = sizeof(struct header); (void)memset(&hd, 0, length); retval = recv_data(dt.sock, &hd, &length); if (retval < 0) /* エラーまたは接続先がシャットダウンされた */ pthread_exit((void *)EXIT_FAILURE); dbglog("recv_data: hd=%p, length=%zu, hd.length=%zu", &hd, length, hd.length); if (g_gflag) outdump(&hd, length, "recv: hd=%p, length=%zu", &hd, length); stddump(&hd, length, "recv: hd=%p, length=%zu", &hd, length); /* データ受信 */ length = (size_t)ntohl((uint32_t)hd.length); /* データ長を保持 */ expr = (unsigned char *)recv_data_new(dt.sock, &length); if (!expr) /* メモリ不足 */ pthread_exit((void *)EXIT_FAILURE); pthread_cleanup_push(thread_memfree, &expr); if (!length) /* 受信エラー */ pthread_exit((void *)EXIT_FAILURE); dbglog("expr=%p, length=%zu", expr, length); if (g_gflag) outdump(expr, length, "recv: expr=%p, length=%zu", expr, length); stddump(expr, length, "recv: expr=%p, length=%zu", expr, length); /* サーバ処理 */ (void)memset(&calc, 0, sizeof(calcinfo)); if (!create_answer(&calc, expr)) pthread_exit((void *)EXIT_FAILURE); pthread_cleanup_push(destroy_answer, &calc); length = strlen((char *)calc.answer) + 1; /* 文字列長保持 */ dbgdump(calc.answer, length, "answer=%p, length=%zu", calc.answer, length); /* データ送信 */ slen = set_server_data(&sdata, calc.answer, length); if (slen < 0) /* メモリ確保できない */ pthread_exit((void *)EXIT_FAILURE); pthread_cleanup_push(thread_memfree, &sdata); dbglog("slen=%zd", slen); if (g_gflag) outdump(sdata, slen, "send: sdata=%p, slen=%zd", sdata, slen); stddump(sdata, slen, "send: sdata=%p, slen=%zd", sdata, slen); retval = send_data(dt.sock, sdata, (size_t *)&slen); if (retval < 0) /* エラー */ pthread_exit((void *)EXIT_FAILURE); dbglog("send_data: sdata=%p, slen=%zu", sdata, slen); pthread_cleanup_pop(1); pthread_cleanup_pop(1); pthread_cleanup_pop(1); } while (!g_sig_handled); pthread_cleanup_pop(1); pthread_exit((void *)EXIT_SUCCESS); return (void *)EXIT_SUCCESS; }