/** int recv_https_closed(int sofd, SSL* ssl, Buffer* buf, int tm, FILE* fp) HTTPメッセージで recv_https_header() で受信したヘッダに引き続いて,Chunkモードのコンテンツデータを受信する. fp がNULLでなければ,受信データ(コンテンツ)はファイルにも保存される. @param sofd 接続相手へのソケット @param ssl 接続相手への SSLソケット.SSL通信でない場合は NULL を指定. @param[in,out] buf 全コンテンツを保存する変数.最初に,recv_https_header()で受信したコンテンツ部分を入れて置く. @param tm タイムアウト秒数. @param fp 受信したコンテンツを保存するファイルディスクリプタ.NULLなら保存しない. @retval 0以上 全コンテンツのサイズ(Byte).recv_https_header()で受信したコンテンツ部分を含む. @retval 0未満 エラー */ int recv_https_closed(int sofd, SSL* ssl, Buffer* buf, int tm, FILE* fp) { int cc, sz, tout; Buffer rcv; sz = buf->vldsz; rcv = make_Buffer(RECVBUFSZ); while ((tout=recv_wait(sofd, tm))) { cc = ssl_tcp_recv_Buffer(sofd, ssl, &rcv); if (cc>0) { if (fp!=NULL) fwrite(rcv.buf, cc, 1, fp); cat_Buffer(&rcv, buf); sz += cc; } else { break; } memset(rcv.buf, 0, cc); } free_Buffer(&rcv); if (!tout) return RECV_TIMEOUTED; return sz; }
/** * Server loop. * * Wait for incoming data from remote peer and if echo mode is on, echo it * back. * * @param ctx Pointer to main context. * @param fd The socket to the remote peer (in SOCK_STREAM mode) or the "server * socket" in SOCK_SEQPKT mode. * @return SERVER_USER_CLOSE if user requested stop (ctrl+c was pressed), * SERVER_ERROR if there was error when receiving data, SERVER_OK if the remote * end closed connetion. */ int do_server( struct server_ctx *ctx, int fd ) { struct sockaddr_storage peer_ss; socklen_t peerlen; struct sctp_sndrcvinfo info; int ret,flags; while( ! close_req ) { memset( &peer_ss, 0, sizeof( peer_ss )); memset( &info, 0, sizeof( peer_ss )); peerlen = sizeof( struct sockaddr_in6); flags = 0; ret = recv_wait( fd, ACCEPT_TIMEOUT_MS, ctx->recvbuf, ctx->recvbuf_size, (struct sockaddr *)&peer_ss, &peerlen, &info, &flags ); if ( ret == -1 ) { if ( errno == EINTR ) continue; print_error("Unable to read data", errno); return SERVER_ERROR; } else if ( ret == -2 ) { printf("Connection closed by remote host\n" ); return SERVER_REMOTE_CLOSED; } else if ( ret > 0 ) { DBG("Received %d bytes \n", ret ); partial_store_collect(&ctx->partial, ctx->recvbuf, ret); if ( flags & MSG_NOTIFICATION ) { TRACE("Received SCTP event\n"); if ( flags & MSG_EOR ) { handle_event(partial_store_dataptr(&ctx->partial)); partial_store_flush(&ctx->partial); } continue; } if (is_flag(ctx->options, VERBOSE_FLAG)) print_input( &peer_ss, ret, flags, &info); else print_input( &peer_ss, ret, flags, NULL); if (is_flag(ctx->options, XDUMP_FLAG)) xdump_data( stdout, ctx->recvbuf, ret, "Received data" ); if ( is_flag( ctx->options, ECHO_FLAG ) && (flags & MSG_EOR) ) { if ( sendit( fd, info.sinfo_ppid, info.sinfo_stream, (struct sockaddr *)&peer_ss, peerlen, partial_store_dataptr( &ctx->partial), partial_store_len( &ctx->partial) ) < 0) { WARN("Error while echoing data!\n"); } else { if (is_flag(ctx->options, VERBOSE_FLAG)) print_output_verbose(&peer_ss, partial_store_len(&ctx->partial), info.sinfo_ppid, info.sinfo_stream); else print_output( &peer_ss, partial_store_len(&ctx->partial)); } } if ( flags & MSG_EOR ) partial_store_flush( &ctx->partial ); } } return SERVER_USER_CLOSE; }