MINOR: http-ana: Add a function to set HTTP termination flags

There is already a function to set termination flags but it is not well
suited for HTTP streams. So a function, dedicated to the HTTP analysis, was
added. This way, this new function will be called for HTTP analysers on
error. And if the error is not caugth at this stage, the generic function
will still be called from process_stream().

Here, by default a PRXCOND error is reported and depending on the stream
state, the reson will be set accordingly:

  * If the backend SC is in INI state, SF_FINST_T is reported on tarpit and
    SF_FINST_R otherwise.

  * SF_FINST_Q is the server connection is queued

  * SF_FINST_C in any connection attempt state (REQ/TAR/ASS/CONN/CER/RDY).
    Except for applets, a SF_FINST_R is reported.

  * Once the server connection is established, SF_FINST_H is reported while
    HTTP_MSG_DATA state on the response side.

  * SF_FINST_L is reported if the response is in HTTP_MSG_DONE state or
    higher and a client error/timeout was reported.

  * Otherwise SF_FINST_D is reported.
This commit is contained in:
Christopher Faulet 2023-01-13 09:06:38 +01:00
parent c1b013bc61
commit 71236dedb9
2 changed files with 49 additions and 0 deletions

View File

@ -62,6 +62,8 @@ int http_forward_proxy_resp(struct stream *s, int final);
struct http_txn *http_create_txn(struct stream *s);
void http_destroy_txn(struct stream *s);
void http_set_term_flags(struct stream *s);
/* for debugging, reports the HTTP/1 message state name (legacy version) */
static inline const char *h1_msg_state_str(enum h1_state msg_state)
{

View File

@ -5249,6 +5249,53 @@ void http_destroy_txn(struct stream *s)
}
void http_set_term_flags(struct stream *s)
{
if (!(s->flags & SF_ERR_MASK))
s->flags |= SF_ERR_PRXCOND;
if (!(s->flags & SF_FINST_MASK)) {
if (s->scb->state == SC_ST_INI) {
/* Before any connection attempt on the server side, we
* are still in the request analysis. Just take case to
* detect tarpit error
*/
if (s->req.analysers & AN_REQ_HTTP_TARPIT)
s->flags |= SF_FINST_T;
else
s->flags |= SF_FINST_R;
}
else if (s->scb->state == SC_ST_QUE)
s->flags |= SF_FINST_Q;
else if (sc_state_in(s->scb->state, SC_SB_REQ|SC_SB_TAR|SC_SB_ASS|SC_SB_CON|SC_SB_CER|SC_SB_RDY)) {
if (unlikely(objt_applet(s->target))) {
s->flags |= SF_FINST_R;
}
else
s->flags |= SF_FINST_C;
}
else {
if (s->txn->rsp.msg_state < HTTP_MSG_DATA) {
/* We are still processing the response headers */
s->flags |= SF_FINST_H;
}
// (res >= done) & (res->flags & shutw)
else if (s->txn->rsp.msg_state >= HTTP_MSG_DONE &&
(s->flags & (SF_ERR_CLITO|SF_ERR_CLICL))) {
/* A client error was reported and we are
* transmitting the last block of data
*/
s->flags |= SF_FINST_L;
}
else {
/* Otherwise we are in DATA phase on both sides */
s->flags |= SF_FINST_D;
}
}
}
}
DECLARE_POOL(pool_head_http_txn, "http_txn", sizeof(struct http_txn));
/*