From: Willy Tarreau Date: Wed, 27 Sep 2023 06:17:17 +0000 (+0200) Subject: MINOR: stream: split stats_dump_full_strm_to_buffer() in two X-Git-Tag: v2.9-dev7~71 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=77ecb3146a168f31d9791342c6efdade6ab436f5;p=thirdparty%2Fhaproxy.git MINOR: stream: split stats_dump_full_strm_to_buffer() in two The function only works with the CLI's appctx and does most of the convenient work of dumping a stream into a buffer (well, the trash buffer for now). Let's split it in two so that most of the work is done in a generic function and that the CLI-specific function relies on that one. The diff looks huge due to the changed indent caused by the extraction of the switch/case statement, but when looked at using diff -b it's small. --- diff --git a/src/stream.c b/src/stream.c index 6e6439e870..6696240bb0 100644 --- a/src/stream.c +++ b/src/stream.c @@ -3238,327 +3238,337 @@ struct show_sess_ctx { int pos; /* last position of the current session's buffer */ }; -/* This function dumps a complete stream state onto the stream connector's - * read buffer. The stream has to be set in strm. It returns 0 if the output - * buffer is full and it needs to be called again, otherwise non-zero. It is - * designed to be called from stats_dump_strm_to_buffer() below. +/* This function appends a complete dump of a stream state onto the trash + * buffer, possibly anonymizing using the specified anon_key. The caller is + * responsible for ensuring that enough room remains in the buffer to dump a + * complete stream at once. */ -static int stats_dump_full_strm_to_buffer(struct stconn *sc, struct stream *strm) +static void strm_dump_to_buffer(struct stream *strm, uint32_t anon_key) { - struct appctx *appctx = __sc_appctx(sc); - struct show_sess_ctx *ctx = appctx->svcctx; struct stconn *scf, *scb; struct tm tm; extern const char *monthname[12]; char pn[INET6_ADDRSTRLEN]; struct connection *conn; struct appctx *tmpctx; - uint32_t anon_key = appctx->cli_anon_key; - - chunk_reset(&trash); - if (ctx->section > 0 && ctx->uid != strm->uniq_id) { - /* stream changed, no need to go any further */ - chunk_appendf(&trash, " *** session terminated while we were watching it ***\n"); - if (applet_putchk(appctx, &trash) == -1) - goto full; - goto done; + get_localtime(strm->logs.accept_date.tv_sec, &tm); + chunk_appendf(&trash, + "%p: [%02d/%s/%04d:%02d:%02d:%02d.%06d] id=%u proto=%s", + strm, + tm.tm_mday, monthname[tm.tm_mon], tm.tm_year+1900, + tm.tm_hour, tm.tm_min, tm.tm_sec, (int)(strm->logs.accept_date.tv_usec), + strm->uniq_id, + strm_li(strm) ? strm_li(strm)->rx.proto->name : "?"); + + conn = objt_conn(strm_orig(strm)); + switch (conn && conn_get_src(conn) ? addr_to_str(conn->src, pn, sizeof(pn)) : AF_UNSPEC) { + case AF_INET: + case AF_INET6: + chunk_appendf(&trash, " source=%s:%d\n", + HA_ANON_STR(anon_key, pn), get_host_port(conn->src)); + break; + case AF_UNIX: + chunk_appendf(&trash, " source=unix:%d\n", strm_li(strm)->luid); + break; + default: + /* no more information to print right now */ + chunk_appendf(&trash, "\n"); + break; + } + + chunk_appendf(&trash, + " flags=0x%x, conn_retries=%d, conn_exp=%s conn_et=0x%03x srv_conn=%p, pend_pos=%p waiting=%d epoch=%#x\n", + strm->flags, strm->conn_retries, + strm->conn_exp ? + tick_is_expired(strm->conn_exp, now_ms) ? "" : + human_time(TICKS_TO_MS(strm->conn_exp - now_ms), + TICKS_TO_MS(1000)) : "", + strm->conn_err_type, strm->srv_conn, strm->pend_pos, + LIST_INLIST(&strm->buffer_wait.list), strm->stream_epoch); + + chunk_appendf(&trash, + " frontend=%s (id=%u mode=%s), listener=%s (id=%u)", + HA_ANON_STR(anon_key, strm_fe(strm)->id), strm_fe(strm)->uuid, proxy_mode_str(strm_fe(strm)->mode), + strm_li(strm) ? strm_li(strm)->name ? strm_li(strm)->name : "?" : "?", + strm_li(strm) ? strm_li(strm)->luid : 0); + + switch (conn && conn_get_dst(conn) ? addr_to_str(conn->dst, pn, sizeof(pn)) : AF_UNSPEC) { + case AF_INET: + case AF_INET6: + chunk_appendf(&trash, " addr=%s:%d\n", + HA_ANON_STR(anon_key, pn), get_host_port(conn->dst)); + break; + case AF_UNIX: + chunk_appendf(&trash, " addr=unix:%d\n", strm_li(strm)->luid); + break; + default: + /* no more information to print right now */ + chunk_appendf(&trash, "\n"); + break; } - switch (ctx->section) { - case 0: /* main status of the stream */ - ctx->uid = strm->uniq_id; - ctx->section = 1; - __fallthrough; - - case 1: - get_localtime(strm->logs.accept_date.tv_sec, &tm); + if (strm->be->cap & PR_CAP_BE) chunk_appendf(&trash, - "%p: [%02d/%s/%04d:%02d:%02d:%02d.%06d] id=%u proto=%s", - strm, - tm.tm_mday, monthname[tm.tm_mon], tm.tm_year+1900, - tm.tm_hour, tm.tm_min, tm.tm_sec, (int)(strm->logs.accept_date.tv_usec), - strm->uniq_id, - strm_li(strm) ? strm_li(strm)->rx.proto->name : "?"); - - conn = objt_conn(strm_orig(strm)); - switch (conn && conn_get_src(conn) ? addr_to_str(conn->src, pn, sizeof(pn)) : AF_UNSPEC) { - case AF_INET: - case AF_INET6: - chunk_appendf(&trash, " source=%s:%d\n", - HA_ANON_STR(anon_key, pn), get_host_port(conn->src)); - break; - case AF_UNIX: - chunk_appendf(&trash, " source=unix:%d\n", strm_li(strm)->luid); - break; - default: - /* no more information to print right now */ - chunk_appendf(&trash, "\n"); - break; - } + " backend=%s (id=%u mode=%s)", + HA_ANON_STR(anon_key, strm->be->id), + strm->be->uuid, proxy_mode_str(strm->be->mode)); + else + chunk_appendf(&trash, " backend= (id=-1 mode=-)"); + + conn = sc_conn(strm->scb); + switch (conn && conn_get_src(conn) ? addr_to_str(conn->src, pn, sizeof(pn)) : AF_UNSPEC) { + case AF_INET: + case AF_INET6: + chunk_appendf(&trash, " addr=%s:%d\n", + HA_ANON_STR(anon_key, pn), get_host_port(conn->src)); + break; + case AF_UNIX: + chunk_appendf(&trash, " addr=unix\n"); + break; + default: + /* no more information to print right now */ + chunk_appendf(&trash, "\n"); + break; + } + if (strm->be->cap & PR_CAP_BE) chunk_appendf(&trash, - " flags=0x%x, conn_retries=%d, conn_exp=%s conn_et=0x%03x srv_conn=%p, pend_pos=%p waiting=%d epoch=%#x\n", - strm->flags, strm->conn_retries, - strm->conn_exp ? - tick_is_expired(strm->conn_exp, now_ms) ? "" : - human_time(TICKS_TO_MS(strm->conn_exp - now_ms), - TICKS_TO_MS(1000)) : "", - strm->conn_err_type, strm->srv_conn, strm->pend_pos, - LIST_INLIST(&strm->buffer_wait.list), strm->stream_epoch); - + " server=%s (id=%u)", + objt_server(strm->target) ? HA_ANON_STR(anon_key, __objt_server(strm->target)->id) : "", + objt_server(strm->target) ? __objt_server(strm->target)->puid : 0); + else + chunk_appendf(&trash, " server= (id=-1)"); + + switch (conn && conn_get_dst(conn) ? addr_to_str(conn->dst, pn, sizeof(pn)) : AF_UNSPEC) { + case AF_INET: + case AF_INET6: + chunk_appendf(&trash, " addr=%s:%d\n", + HA_ANON_STR(anon_key, pn), get_host_port(conn->dst)); + break; + case AF_UNIX: + chunk_appendf(&trash, " addr=unix\n"); + break; + default: + /* no more information to print right now */ + chunk_appendf(&trash, "\n"); + break; + } + + chunk_appendf(&trash, + " task=%p (state=0x%02x nice=%d calls=%u rate=%u exp=%s tid=%d(%d/%d)%s", + strm->task, + strm->task->state, + strm->task->nice, strm->task->calls, read_freq_ctr(&strm->call_rate), + strm->task->expire ? + tick_is_expired(strm->task->expire, now_ms) ? "" : + human_time(TICKS_TO_MS(strm->task->expire - now_ms), + TICKS_TO_MS(1000)) : "", + strm->task->tid, + ha_thread_info[strm->task->tid].tgid, + ha_thread_info[strm->task->tid].ltid, + task_in_rq(strm->task) ? ", running" : ""); + + chunk_appendf(&trash, + " age=%s)\n", + human_time(ns_to_sec(now_ns) - ns_to_sec(strm->logs.accept_ts), 1)); + + if (strm->txn) chunk_appendf(&trash, - " frontend=%s (id=%u mode=%s), listener=%s (id=%u)", - HA_ANON_STR(anon_key, strm_fe(strm)->id), strm_fe(strm)->uuid, proxy_mode_str(strm_fe(strm)->mode), - strm_li(strm) ? strm_li(strm)->name ? strm_li(strm)->name : "?" : "?", - strm_li(strm) ? strm_li(strm)->luid : 0); - - switch (conn && conn_get_dst(conn) ? addr_to_str(conn->dst, pn, sizeof(pn)) : AF_UNSPEC) { - case AF_INET: - case AF_INET6: - chunk_appendf(&trash, " addr=%s:%d\n", - HA_ANON_STR(anon_key, pn), get_host_port(conn->dst)); - break; - case AF_UNIX: - chunk_appendf(&trash, " addr=unix:%d\n", strm_li(strm)->luid); - break; - default: - /* no more information to print right now */ + " txn=%p flags=0x%x meth=%d status=%d req.st=%s rsp.st=%s req.f=0x%02x rsp.f=0x%02x\n", + strm->txn, strm->txn->flags, strm->txn->meth, strm->txn->status, + h1_msg_state_str(strm->txn->req.msg_state), h1_msg_state_str(strm->txn->rsp.msg_state), + strm->txn->req.flags, strm->txn->rsp.flags); + + scf = strm->scf; + chunk_appendf(&trash, " scf=%p flags=0x%08x state=%s endp=%s,%p,0x%08x sub=%d", + scf, scf->flags, sc_state_str(scf->state), + (sc_ep_test(scf, SE_FL_T_MUX) ? "CONN" : (sc_ep_test(scf, SE_FL_T_APPLET) ? "APPCTX" : "NONE")), + scf->sedesc->se, sc_ep_get(scf), scf->wait_event.events); + chunk_appendf(&trash, " rex=%s", + sc_ep_rcv_ex(scf) ? human_time(TICKS_TO_MS(sc_ep_rcv_ex(scf) - now_ms), TICKS_TO_MS(1000)) : ""); + chunk_appendf(&trash, " wex=%s\n", + sc_ep_snd_ex(scf) ? human_time(TICKS_TO_MS(sc_ep_snd_ex(scf) - now_ms), TICKS_TO_MS(1000)) : ""); + + if ((conn = sc_conn(scf)) != NULL) { + if (conn->mux && conn->mux->show_sd) { + chunk_appendf(&trash, " "); + conn->mux->show_sd(&trash, scf->sedesc, " "); chunk_appendf(&trash, "\n"); - break; - } - - if (strm->be->cap & PR_CAP_BE) - chunk_appendf(&trash, - " backend=%s (id=%u mode=%s)", - HA_ANON_STR(anon_key, strm->be->id), - strm->be->uuid, proxy_mode_str(strm->be->mode)); - else - chunk_appendf(&trash, " backend= (id=-1 mode=-)"); - - conn = sc_conn(strm->scb); - switch (conn && conn_get_src(conn) ? addr_to_str(conn->src, pn, sizeof(pn)) : AF_UNSPEC) { - case AF_INET: - case AF_INET6: - chunk_appendf(&trash, " addr=%s:%d\n", - HA_ANON_STR(anon_key, pn), get_host_port(conn->src)); - break; - case AF_UNIX: - chunk_appendf(&trash, " addr=unix\n"); - break; - default: - /* no more information to print right now */ - chunk_appendf(&trash, "\n"); - break; } - if (strm->be->cap & PR_CAP_BE) - chunk_appendf(&trash, - " server=%s (id=%u)", - objt_server(strm->target) ? HA_ANON_STR(anon_key, __objt_server(strm->target)->id) : "", - objt_server(strm->target) ? __objt_server(strm->target)->puid : 0); - else - chunk_appendf(&trash, " server= (id=-1)"); + chunk_appendf(&trash, + " co0=%p ctrl=%s xprt=%s mux=%s data=%s target=%s:%p\n", + conn, + conn_get_ctrl_name(conn), + conn_get_xprt_name(conn), + conn_get_mux_name(conn), + sc_get_data_name(scf), + obj_type_name(conn->target), + obj_base_ptr(conn->target)); - switch (conn && conn_get_dst(conn) ? addr_to_str(conn->dst, pn, sizeof(pn)) : AF_UNSPEC) { - case AF_INET: - case AF_INET6: - chunk_appendf(&trash, " addr=%s:%d\n", - HA_ANON_STR(anon_key, pn), get_host_port(conn->dst)); - break; - case AF_UNIX: - chunk_appendf(&trash, " addr=unix\n"); - break; - default: - /* no more information to print right now */ + chunk_appendf(&trash, + " flags=0x%08x fd=%d fd.state=%02x updt=%d fd.tmask=0x%lx\n", + conn->flags, + conn_fd(conn), + conn_fd(conn) >= 0 ? fdtab[conn->handle.fd].state : 0, + conn_fd(conn) >= 0 ? !!(fdtab[conn->handle.fd].update_mask & ti->ltid_bit) : 0, + conn_fd(conn) >= 0 ? fdtab[conn->handle.fd].thread_mask: 0); + } + else if ((tmpctx = sc_appctx(scf)) != NULL) { + chunk_appendf(&trash, + " app0=%p st0=%d st1=%d applet=%s tid=%d nice=%d calls=%u rate=%u\n", + tmpctx, + tmpctx->st0, + tmpctx->st1, + tmpctx->applet->name, + tmpctx->t->tid, + tmpctx->t->nice, tmpctx->t->calls, read_freq_ctr(&tmpctx->call_rate)); + } + + scb = strm->scb; + chunk_appendf(&trash, " scb=%p flags=0x%08x state=%s endp=%s,%p,0x%08x sub=%d", + scb, scb->flags, sc_state_str(scb->state), + (sc_ep_test(scb, SE_FL_T_MUX) ? "CONN" : (sc_ep_test(scb, SE_FL_T_APPLET) ? "APPCTX" : "NONE")), + scb->sedesc->se, sc_ep_get(scb), scb->wait_event.events); + chunk_appendf(&trash, " rex=%s", + sc_ep_rcv_ex(scb) ? human_time(TICKS_TO_MS(sc_ep_rcv_ex(scb) - now_ms), TICKS_TO_MS(1000)) : ""); + chunk_appendf(&trash, " wex=%s\n", + sc_ep_snd_ex(scb) ? human_time(TICKS_TO_MS(sc_ep_snd_ex(scb) - now_ms), TICKS_TO_MS(1000)) : ""); + + if ((conn = sc_conn(scb)) != NULL) { + if (conn->mux && conn->mux->show_sd) { + chunk_appendf(&trash, " "); + conn->mux->show_sd(&trash, scb->sedesc, " "); chunk_appendf(&trash, "\n"); - break; } chunk_appendf(&trash, - " task=%p (state=0x%02x nice=%d calls=%u rate=%u exp=%s tid=%d(%d/%d)%s", - strm->task, - strm->task->state, - strm->task->nice, strm->task->calls, read_freq_ctr(&strm->call_rate), - strm->task->expire ? - tick_is_expired(strm->task->expire, now_ms) ? "" : - human_time(TICKS_TO_MS(strm->task->expire - now_ms), - TICKS_TO_MS(1000)) : "", - strm->task->tid, - ha_thread_info[strm->task->tid].tgid, - ha_thread_info[strm->task->tid].ltid, - task_in_rq(strm->task) ? ", running" : ""); + " co1=%p ctrl=%s xprt=%s mux=%s data=%s target=%s:%p\n", + conn, + conn_get_ctrl_name(conn), + conn_get_xprt_name(conn), + conn_get_mux_name(conn), + sc_get_data_name(scb), + obj_type_name(conn->target), + obj_base_ptr(conn->target)); chunk_appendf(&trash, - " age=%s)\n", - human_time(ns_to_sec(now_ns) - ns_to_sec(strm->logs.accept_ts), 1)); - - if (strm->txn) - chunk_appendf(&trash, - " txn=%p flags=0x%x meth=%d status=%d req.st=%s rsp.st=%s req.f=0x%02x rsp.f=0x%02x\n", - strm->txn, strm->txn->flags, strm->txn->meth, strm->txn->status, - h1_msg_state_str(strm->txn->req.msg_state), h1_msg_state_str(strm->txn->rsp.msg_state), - strm->txn->req.flags, strm->txn->rsp.flags); - - scf = strm->scf; - chunk_appendf(&trash, " scf=%p flags=0x%08x state=%s endp=%s,%p,0x%08x sub=%d", - scf, scf->flags, sc_state_str(scf->state), - (sc_ep_test(scf, SE_FL_T_MUX) ? "CONN" : (sc_ep_test(scf, SE_FL_T_APPLET) ? "APPCTX" : "NONE")), - scf->sedesc->se, sc_ep_get(scf), scf->wait_event.events); - chunk_appendf(&trash, " rex=%s", - sc_ep_rcv_ex(scf) ? human_time(TICKS_TO_MS(sc_ep_rcv_ex(scf) - now_ms), TICKS_TO_MS(1000)) : ""); - chunk_appendf(&trash, " wex=%s\n", - sc_ep_snd_ex(scf) ? human_time(TICKS_TO_MS(sc_ep_snd_ex(scf) - now_ms), TICKS_TO_MS(1000)) : ""); - - if ((conn = sc_conn(scf)) != NULL) { - if (conn->mux && conn->mux->show_sd) { - chunk_appendf(&trash, " "); - conn->mux->show_sd(&trash, scf->sedesc, " "); - chunk_appendf(&trash, "\n"); - } - - chunk_appendf(&trash, - " co0=%p ctrl=%s xprt=%s mux=%s data=%s target=%s:%p\n", - conn, - conn_get_ctrl_name(conn), - conn_get_xprt_name(conn), - conn_get_mux_name(conn), - sc_get_data_name(scf), - obj_type_name(conn->target), - obj_base_ptr(conn->target)); - - chunk_appendf(&trash, - " flags=0x%08x fd=%d fd.state=%02x updt=%d fd.tmask=0x%lx\n", - conn->flags, - conn_fd(conn), - conn_fd(conn) >= 0 ? fdtab[conn->handle.fd].state : 0, - conn_fd(conn) >= 0 ? !!(fdtab[conn->handle.fd].update_mask & ti->ltid_bit) : 0, - conn_fd(conn) >= 0 ? fdtab[conn->handle.fd].thread_mask: 0); - } - else if ((tmpctx = sc_appctx(scf)) != NULL) { - chunk_appendf(&trash, - " app0=%p st0=%d st1=%d applet=%s tid=%d nice=%d calls=%u rate=%u\n", - tmpctx, - tmpctx->st0, - tmpctx->st1, - tmpctx->applet->name, - tmpctx->t->tid, - tmpctx->t->nice, tmpctx->t->calls, read_freq_ctr(&tmpctx->call_rate)); - } - - scb = strm->scb; - chunk_appendf(&trash, " scb=%p flags=0x%08x state=%s endp=%s,%p,0x%08x sub=%d", - scb, scb->flags, sc_state_str(scb->state), - (sc_ep_test(scb, SE_FL_T_MUX) ? "CONN" : (sc_ep_test(scb, SE_FL_T_APPLET) ? "APPCTX" : "NONE")), - scb->sedesc->se, sc_ep_get(scb), scb->wait_event.events); - chunk_appendf(&trash, " rex=%s", - sc_ep_rcv_ex(scb) ? human_time(TICKS_TO_MS(sc_ep_rcv_ex(scb) - now_ms), TICKS_TO_MS(1000)) : ""); - chunk_appendf(&trash, " wex=%s\n", - sc_ep_snd_ex(scb) ? human_time(TICKS_TO_MS(sc_ep_snd_ex(scb) - now_ms), TICKS_TO_MS(1000)) : ""); - - if ((conn = sc_conn(scb)) != NULL) { - if (conn->mux && conn->mux->show_sd) { - chunk_appendf(&trash, " "); - conn->mux->show_sd(&trash, scb->sedesc, " "); - chunk_appendf(&trash, "\n"); - } - - chunk_appendf(&trash, - " co1=%p ctrl=%s xprt=%s mux=%s data=%s target=%s:%p\n", - conn, - conn_get_ctrl_name(conn), - conn_get_xprt_name(conn), - conn_get_mux_name(conn), - sc_get_data_name(scb), - obj_type_name(conn->target), - obj_base_ptr(conn->target)); + " flags=0x%08x fd=%d fd.state=%02x updt=%d fd.tmask=0x%lx\n", + conn->flags, + conn_fd(conn), + conn_fd(conn) >= 0 ? fdtab[conn->handle.fd].state : 0, + conn_fd(conn) >= 0 ? !!(fdtab[conn->handle.fd].update_mask & ti->ltid_bit) : 0, + conn_fd(conn) >= 0 ? fdtab[conn->handle.fd].thread_mask: 0); + } + else if ((tmpctx = sc_appctx(scb)) != NULL) { + chunk_appendf(&trash, + " app1=%p st0=%d st1=%d applet=%s tid=%d nice=%d calls=%u rate=%u\n", + tmpctx, + tmpctx->st0, + tmpctx->st1, + tmpctx->applet->name, + tmpctx->t->tid, + tmpctx->t->nice, tmpctx->t->calls, read_freq_ctr(&tmpctx->call_rate)); + } + + chunk_appendf(&trash, + " req=%p (f=0x%06x an=0x%x pipe=%d tofwd=%d total=%lld)\n" + " an_exp=%s buf=%p data=%p o=%u p=%u i=%u size=%u\n", + &strm->req, + strm->req.flags, strm->req.analysers, + strm->req.pipe ? strm->req.pipe->data : 0, + strm->req.to_forward, strm->req.total, + strm->req.analyse_exp ? + human_time(TICKS_TO_MS(strm->req.analyse_exp - now_ms), + TICKS_TO_MS(1000)) : "", + &strm->req.buf, + b_orig(&strm->req.buf), (unsigned int)co_data(&strm->req), + (unsigned int)ci_head_ofs(&strm->req), (unsigned int)ci_data(&strm->req), + (unsigned int)strm->req.buf.size); + + if (IS_HTX_STRM(strm)) { + struct htx *htx = htxbuf(&strm->req.buf); - chunk_appendf(&trash, - " flags=0x%08x fd=%d fd.state=%02x updt=%d fd.tmask=0x%lx\n", - conn->flags, - conn_fd(conn), - conn_fd(conn) >= 0 ? fdtab[conn->handle.fd].state : 0, - conn_fd(conn) >= 0 ? !!(fdtab[conn->handle.fd].update_mask & ti->ltid_bit) : 0, - conn_fd(conn) >= 0 ? fdtab[conn->handle.fd].thread_mask: 0); - } - else if ((tmpctx = sc_appctx(scb)) != NULL) { - chunk_appendf(&trash, - " app1=%p st0=%d st1=%d applet=%s tid=%d nice=%d calls=%u rate=%u\n", - tmpctx, - tmpctx->st0, - tmpctx->st1, - tmpctx->applet->name, - tmpctx->t->tid, - tmpctx->t->nice, tmpctx->t->calls, read_freq_ctr(&tmpctx->call_rate)); - } + chunk_appendf(&trash, + " htx=%p flags=0x%x size=%u data=%u used=%u wrap=%s extra=%llu\n", + htx, htx->flags, htx->size, htx->data, htx_nbblks(htx), + (htx->tail >= htx->head) ? "NO" : "YES", + (unsigned long long)htx->extra); + } + if (HAS_FILTERS(strm) && strm_flt(strm)->current[0]) { + struct filter *flt = strm_flt(strm)->current[0]; + + chunk_appendf(&trash, " current_filter=%p (id=\"%s\" flags=0x%x pre=0x%x post=0x%x) \n", + flt, flt->config->id, flt->flags, flt->pre_analyzers, flt->post_analyzers); + } + + chunk_appendf(&trash, + " res=%p (f=0x%06x an=0x%x pipe=%d tofwd=%d total=%lld)\n" + " an_exp=%s buf=%p data=%p o=%u p=%u i=%u size=%u\n", + &strm->res, + strm->res.flags, strm->res.analysers, + strm->res.pipe ? strm->res.pipe->data : 0, + strm->res.to_forward, strm->res.total, + strm->res.analyse_exp ? + human_time(TICKS_TO_MS(strm->res.analyse_exp - now_ms), + TICKS_TO_MS(1000)) : "", + &strm->res.buf, + b_orig(&strm->res.buf), (unsigned int)co_data(&strm->res), + (unsigned int)ci_head_ofs(&strm->res), (unsigned int)ci_data(&strm->res), + (unsigned int)strm->res.buf.size); + + if (IS_HTX_STRM(strm)) { + struct htx *htx = htxbuf(&strm->res.buf); chunk_appendf(&trash, - " req=%p (f=0x%06x an=0x%x pipe=%d tofwd=%d total=%lld)\n" - " an_exp=%s buf=%p data=%p o=%u p=%u i=%u size=%u\n", - &strm->req, - strm->req.flags, strm->req.analysers, - strm->req.pipe ? strm->req.pipe->data : 0, - strm->req.to_forward, strm->req.total, - strm->req.analyse_exp ? - human_time(TICKS_TO_MS(strm->req.analyse_exp - now_ms), - TICKS_TO_MS(1000)) : "", - &strm->req.buf, - b_orig(&strm->req.buf), (unsigned int)co_data(&strm->req), - (unsigned int)ci_head_ofs(&strm->req), (unsigned int)ci_data(&strm->req), - (unsigned int)strm->req.buf.size); - - if (IS_HTX_STRM(strm)) { - struct htx *htx = htxbuf(&strm->req.buf); + " htx=%p flags=0x%x size=%u data=%u used=%u wrap=%s extra=%llu\n", + htx, htx->flags, htx->size, htx->data, htx_nbblks(htx), + (htx->tail >= htx->head) ? "NO" : "YES", + (unsigned long long)htx->extra); + } + if (HAS_FILTERS(strm) && strm_flt(strm)->current[1]) { + struct filter *flt = strm_flt(strm)->current[1]; - chunk_appendf(&trash, - " htx=%p flags=0x%x size=%u data=%u used=%u wrap=%s extra=%llu\n", - htx, htx->flags, htx->size, htx->data, htx_nbblks(htx), - (htx->tail >= htx->head) ? "NO" : "YES", - (unsigned long long)htx->extra); - } - if (HAS_FILTERS(strm) && strm_flt(strm)->current[0]) { - struct filter *flt = strm_flt(strm)->current[0]; + chunk_appendf(&trash, " current_filter=%p (id=\"%s\" flags=0x%x pre=0x%x post=0x%x) \n", + flt, flt->config->id, flt->flags, flt->pre_analyzers, flt->post_analyzers); + } - chunk_appendf(&trash, " current_filter=%p (id=\"%s\" flags=0x%x pre=0x%x post=0x%x) \n", - flt, flt->config->id, flt->flags, flt->pre_analyzers, flt->post_analyzers); - } + if (strm->current_rule_list && strm->current_rule) { + const struct act_rule *rule = strm->current_rule; + chunk_appendf(&trash, " current_rule=\"%s\" [%s:%d]\n", rule->kw->kw, rule->conf.file, rule->conf.line); + } +} - chunk_appendf(&trash, - " res=%p (f=0x%06x an=0x%x pipe=%d tofwd=%d total=%lld)\n" - " an_exp=%s buf=%p data=%p o=%u p=%u i=%u size=%u\n", - &strm->res, - strm->res.flags, strm->res.analysers, - strm->res.pipe ? strm->res.pipe->data : 0, - strm->res.to_forward, strm->res.total, - strm->res.analyse_exp ? - human_time(TICKS_TO_MS(strm->res.analyse_exp - now_ms), - TICKS_TO_MS(1000)) : "", - &strm->res.buf, - b_orig(&strm->res.buf), (unsigned int)co_data(&strm->res), - (unsigned int)ci_head_ofs(&strm->res), (unsigned int)ci_data(&strm->res), - (unsigned int)strm->res.buf.size); - - if (IS_HTX_STRM(strm)) { - struct htx *htx = htxbuf(&strm->res.buf); +/* This function dumps a complete stream state onto the stream connector's + * read buffer. The stream has to be set in strm. It returns 0 if the output + * buffer is full and it needs to be called again, otherwise non-zero. It is + * designed to be called from stats_dump_strm_to_buffer() below. + */ +static int stats_dump_full_strm_to_buffer(struct stconn *sc, struct stream *strm) +{ + struct appctx *appctx = __sc_appctx(sc); + struct show_sess_ctx *ctx = appctx->svcctx; - chunk_appendf(&trash, - " htx=%p flags=0x%x size=%u data=%u used=%u wrap=%s extra=%llu\n", - htx, htx->flags, htx->size, htx->data, htx_nbblks(htx), - (htx->tail >= htx->head) ? "NO" : "YES", - (unsigned long long)htx->extra); - } - if (HAS_FILTERS(strm) && strm_flt(strm)->current[1]) { - struct filter *flt = strm_flt(strm)->current[1]; + chunk_reset(&trash); - chunk_appendf(&trash, " current_filter=%p (id=\"%s\" flags=0x%x pre=0x%x post=0x%x) \n", - flt, flt->config->id, flt->flags, flt->pre_analyzers, flt->post_analyzers); - } + if (ctx->section > 0 && ctx->uid != strm->uniq_id) { + /* stream changed, no need to go any further */ + chunk_appendf(&trash, " *** session terminated while we were watching it ***\n"); + if (applet_putchk(appctx, &trash) == -1) + goto full; + goto done; + } - if (strm->current_rule_list && strm->current_rule) { - const struct act_rule *rule = strm->current_rule; - chunk_appendf(&trash, " current_rule=\"%s\" [%s:%d]\n", rule->kw->kw, rule->conf.file, rule->conf.line); - } + switch (ctx->section) { + case 0: /* main status of the stream */ + ctx->uid = strm->uniq_id; + ctx->section = 1; + __fallthrough; + case 1: + /* the function appends to the trash */ + strm_dump_to_buffer(strm, appctx->cli_anon_key); if (applet_putchk(appctx, &trash) == -1) goto full;