int stats_putchk(struct appctx *appctx, struct htx *htx)
{
- struct stconn *sc = appctx_sc(appctx);
- struct channel *chn = sc_ic(sc);
struct buffer *chk = &trash_chunk;
if (htx) {
- if (chk->data >= channel_htx_recv_max(chn, htx)) {
- sc_need_room(sc, chk->data);
+ if (chk->data > htx_free_data_space(htx)) {
+ applet_fl_set(appctx, APPCTX_FL_OUTBLK_FULL);
return 0;
}
if (!htx_add_data_atonce(htx, ist2(chk->area, chk->data))) {
- sc_need_room(sc, 0);
+ applet_fl_set(appctx, APPCTX_FL_OUTBLK_FULL);
return 0;
}
- channel_add_input(chn, chk->data);
chk->data = 0;
}
else {
return 1;
}
-static const char *stats_scope_ptr(struct appctx *appctx, struct stconn *sc)
+static const char *stats_scope_ptr(struct appctx *appctx)
{
struct show_stat_ctx *ctx = appctx->svcctx;
- struct channel *req = sc_oc(sc);
- struct htx *htx = htxbuf(&req->buf);
+ struct htx *htx = htxbuf(&appctx->inbuf);
struct htx_blk *blk;
struct ist uri;
/* scope_txt = search pattern + search query, ctx->scope_len is always <= STAT_SCOPE_TXT_MAXLEN */
scope_txt[0] = 0;
if (ctx->scope_len) {
- const char *scope_ptr = stats_scope_ptr(appctx, sc);
+ const char *scope_ptr = stats_scope_ptr(appctx);
strlcpy2(scope_txt, STAT_SCOPE_PATTERN, sizeof(scope_txt));
memcpy(scope_txt + strlen(STAT_SCOPE_PATTERN), scope_ptr, ctx->scope_len);
{
struct appctx *appctx = __sc_appctx(sc);
struct show_stat_ctx *ctx = appctx->svcctx;
- struct channel *rep = sc_ic(sc);
struct server *sv, *svs; /* server and server-state, server-state=server or server->track */
struct listener *l;
struct uri_auth *uri = NULL;
* name does not match, skip it.
*/
if (ctx->scope_len) {
- const char *scope_ptr = stats_scope_ptr(appctx, sc);
+ const char *scope_ptr = stats_scope_ptr(appctx);
if (strnistr(px->id, strlen(px->id), scope_ptr, ctx->scope_len) == NULL)
return 1;
for (; ctx->obj2 != &px->conf.listeners; ctx->obj2 = l->by_fe.n) {
if (htx) {
if (htx_almost_full(htx)) {
- sc_need_room(sc, htx->size / 2);
+ appctx->flags |= APPCTX_FL_OUTBLK_FULL;
goto full;
}
}
else {
+ struct channel *rep = sc_ic(appctx_sc(appctx));
+
if (buffer_almost_full(&rep->buf)) {
sc_need_room(sc, b_size(&rep->buf) / 2);
goto full;
if (htx) {
if (htx_almost_full(htx)) {
- sc_need_room(sc, htx->size / 2);
+ appctx->flags |= APPCTX_FL_OUTBLK_FULL;
goto full;
}
}
else {
+ struct channel *rep = sc_ic(appctx_sc(appctx));
+
if (buffer_almost_full(&rep->buf)) {
sc_need_room(sc, b_size(&rep->buf) / 2);
goto full;
struct show_stat_ctx *ctx = appctx->svcctx;
unsigned int up = ns_to_sec(now_ns - start_time_ns);
char scope_txt[STAT_SCOPE_TXT_MAXLEN + sizeof STAT_SCOPE_PATTERN];
- const char *scope_ptr = stats_scope_ptr(appctx, sc);
+ const char *scope_ptr = stats_scope_ptr(appctx);
struct uri_auth *uri;
unsigned long long bps;
int thr;
{
struct appctx *appctx = __sc_appctx(sc);
struct show_stat_ctx *ctx = appctx->svcctx;
- struct channel *rep = sc_ic(sc);
struct proxy *px;
/* dump proxies */
while (ctx->obj1) {
if (htx) {
if (htx_almost_full(htx)) {
- sc_need_room(sc, htx->size / 2);
+ appctx->flags |= APPCTX_FL_OUTBLK_FULL;
goto full;
}
}
else {
+ struct channel *rep = sc_ic(appctx_sc(appctx));
+
if (buffer_almost_full(&rep->buf)) {
sc_need_room(sc, b_size(&rep->buf) / 2);
goto full;
*/
static int stats_process_http_post(struct stconn *sc)
{
- struct stream *s = __sc_strm(sc);
struct appctx *appctx = __sc_appctx(sc);
struct show_stat_ctx *ctx = appctx->svcctx;
struct buffer *temp = get_trash_chunk();
- struct htx *htx = htxbuf(&s->req.buf);
+ struct htx *htx = htxbuf(&appctx->inbuf);
struct htx_blk *blk;
/* we need more data */
- if (s->txn->req.msg_state < HTTP_MSG_DONE) {
+ if (!(htx->flags & HTX_FL_EOM)) {
/* check if we can receive more */
- if (htx_free_data_space(htx) <= global.tune.maxrewrite) {
+ if (applet_fl_test(appctx, APPCTX_FL_INBLK_FULL)) {
ctx->st_code = STAT_STATUS_EXCD;
goto out;
}
- goto wait;
+ goto wait;
}
/* The request was fully received. Copy data */
static int stats_send_http_headers(struct stconn *sc, struct htx *htx)
{
- struct stream *s = __sc_strm(sc);
struct uri_auth *uri;
struct appctx *appctx = __sc_appctx(sc);
struct show_stat_ctx *ctx = appctx->svcctx;
if (!htx_add_endof(htx, HTX_BLK_EOH))
goto full;
-
- channel_add_input(&s->res, htx->data);
return 1;
full:
htx_reset(htx);
- sc_need_room(sc, 0);
+ applet_set_eos(appctx);
+ applet_set_error(appctx);
return 0;
}
static int stats_send_http_redirect(struct stconn *sc, struct htx *htx)
{
char scope_txt[STAT_SCOPE_TXT_MAXLEN + sizeof STAT_SCOPE_PATTERN];
- struct stream *s = __sc_strm(sc);
struct uri_auth *uri;
struct appctx *appctx = __sc_appctx(sc);
struct show_stat_ctx *ctx = appctx->svcctx;
/* scope_txt = search pattern + search query, ctx->scope_len is always <= STAT_SCOPE_TXT_MAXLEN */
scope_txt[0] = 0;
if (ctx->scope_len) {
- const char *scope_ptr = stats_scope_ptr(appctx, sc);
+ const char *scope_ptr = stats_scope_ptr(appctx);
strlcpy2(scope_txt, STAT_SCOPE_PATTERN, sizeof(scope_txt));
memcpy(scope_txt + strlen(STAT_SCOPE_PATTERN), scope_ptr, ctx->scope_len);
if (!htx_add_endof(htx, HTX_BLK_EOH))
goto full;
- channel_add_input(&s->res, htx->data);
return 1;
-full:
+ full:
htx_reset(htx);
- sc_need_room(sc, 0);
+ applet_set_eos(appctx);
+ applet_set_error(appctx);
return 0;
}
{
struct show_stat_ctx *ctx = appctx->svcctx;
struct stconn *sc = appctx_sc(appctx);
- struct stream *s = __sc_strm(sc);
- struct channel *req = sc_oc(sc);
- struct channel *res = sc_ic(sc);
- struct htx *req_htx, *res_htx;
+ struct htx *res_htx = NULL;
/* only proxy stats are available via http */
ctx->domain = STATS_DOMAIN_PROXY;
- res_htx = htx_from_buf(&res->buf);
+ if (applet_fl_test(appctx, APPCTX_FL_OUTBLK_ALLOC|APPCTX_FL_OUTBLK_FULL))
+ goto out;
- if (unlikely(se_fl_test(appctx->sedesc, (SE_FL_EOS|SE_FL_ERROR|SE_FL_SHR|SE_FL_SHW)))) {
- appctx->st0 = STAT_HTTP_END;
+ if (!appctx_get_buf(appctx, &appctx->outbuf)) {
+ appctx->flags |= APPCTX_FL_OUTBLK_ALLOC;
goto out;
}
- /* Check if the input buffer is available. */
- if (!b_size(&res->buf)) {
- sc_need_room(sc, 0);
+ res_htx = htx_from_buf(&appctx->outbuf);
+
+ if (unlikely(applet_fl_test(appctx, APPCTX_FL_EOS|APPCTX_FL_ERROR|APPCTX_FL_SHUTDOWN))) {
+ appctx->st0 = STAT_HTTP_END;
goto out;
}
/* all states are processed in sequence */
if (appctx->st0 == STAT_HTTP_HEAD) {
if (stats_send_http_headers(sc, res_htx)) {
- if (s->txn->meth == HTTP_METH_HEAD)
+ struct ist meth = htx_sl_req_meth(http_get_stline(htxbuf(&appctx->inbuf)));
+
+ if (find_http_meth(istptr(meth), istlen(meth)) == HTTP_METH_HEAD)
appctx->st0 = STAT_HTTP_DONE;
else
appctx->st0 = STAT_HTTP_DUMP;
}
if (appctx->st0 == STAT_HTTP_DUMP) {
- trash_chunk = b_make(trash.area, res->buf.size, 0, 0);
+ trash_chunk = b_make(trash.area, appctx->outbuf.size, 0, 0);
/* adjust buffer size to take htx overhead into account,
* make sure to perform this call on an empty buffer
*/
*/
if (htx_is_empty(res_htx)) {
if (!htx_add_endof(res_htx, HTX_BLK_EOT)) {
- sc_need_room(sc, sizeof(struct htx_blk) + 1);
+ appctx->flags |= APPCTX_FL_OUTBLK_FULL;
goto out;
}
- channel_add_input(res, 1);
}
res_htx->flags |= HTX_FL_EOM;
- se_fl_set(appctx->sedesc, SE_FL_EOI);
+ applet_set_eoi(appctx);
appctx->st0 = STAT_HTTP_END;
}
if (appctx->st0 == STAT_HTTP_END) {
- se_fl_set(appctx->sedesc, SE_FL_EOS);
+ applet_set_eos(appctx);
applet_will_consume(appctx);
}
* deciding to wake the applet up. It saves it from looping when
* emitting large blocks into small TCP windows.
*/
- htx_to_buf(res_htx, &res->buf);
+ if (res_htx)
+ htx_to_buf(res_htx, &appctx->outbuf);
+
if (appctx->st0 == STAT_HTTP_END) {
/* eat the whole request */
- if (co_data(req)) {
- req_htx = htx_from_buf(&req->buf);
- co_htx_skip(req, req_htx, co_data(req));
- htx_to_buf(req_htx, &req->buf);
- }
+ b_reset(&appctx->inbuf);
+ applet_fl_clr(appctx, APPCTX_FL_INBLK_FULL);
}
- else if (co_data(res))
+ else if (applet_fl_test(appctx, APPCTX_FL_OUTBLK_FULL))
applet_wont_consume(appctx);
}
.obj_type = OBJ_TYPE_APPLET,
.name = "<STATS>", /* used for logging */
.fct = http_stats_io_handler,
+ .rcv_buf = appctx_rcv_buf,
+ .snd_buf = appctx_snd_buf,
.release = NULL,
};