From: Christopher Faulet Date: Tue, 4 Oct 2022 15:13:32 +0000 (+0200) Subject: MINOR: mux-h1: Add a dedicated enum to deal with H1 connection state X-Git-Tag: v2.7-dev9~33 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ef93be2a7b9a71492352266909ecb4a32cb52092;p=thirdparty%2Fhaproxy.git MINOR: mux-h1: Add a dedicated enum to deal with H1 connection state The H1 connection state will be handled is a dedicated field. To do so, h1_cs enum was added. The different states are more or less equivalent to H1C_F_ST_* flags: * H1_CS_IDLE <=> H1C_F_ST_IDLE * H1_CS_EMBRYONIC <=> H1C_F_ST_EMBRYONIC * H1_CS_UPGRADING <=> H1C_F_ST_ATTACHED && !H1C_F_ST_READY * H1_CS_RUNNING <=> H1C_F_ST_ATTACHED && H1C_F_ST_READY * H1_CS_CLOSING <=> H1C_F_ST_SHUTDOWN && (H1C_F_ST_ATTACHED || b_data(&h1c->ibuf)) * H1_CS_CLOSED <=> H1C_F_ST_SHUTDOWN && !H1C_F_ST_ATTACHED && !b_data(&h1c->ibuf) In addition, in this patch, the h1_is_alive() and h1_close() function are added. The first one will be used to know if a H1 connection is alive or not. The second one will be used to set the connection in CLOSING or CLOSED state, depending on the output buffer state and if there is still a H1 stream or not. For now, the H1 connection state is not used. --- diff --git a/include/haproxy/mux_h1-t.h b/include/haproxy/mux_h1-t.h index dcc547ab61..abe5cb87b4 100644 --- a/include/haproxy/mux_h1-t.h +++ b/include/haproxy/mux_h1-t.h @@ -131,5 +131,33 @@ static forceinline char *h1s_show_flags(char *buf, size_t len, const char *delim #undef _ } +/* H1 connection state, in h1c->state */ +enum h1_cs { + H1_CS_IDLE, /* IDLE connection. A freashly open or a reusable connection (H1S is NULL) */ + H1_CS_EMBRYONIC, /* Connection is waiting for the message headers (H1S is not NULL, not attached to a SC - Frontend connection only) */ + H1_CS_UPGRADING, /* TCP>H1 upgrade in-progress (H1S is not NULL and attached to a SC - Frontend connection only) */ + H1_CS_RUNNING, /* Connection fully established and the H1S is processing data (H1S is not NULL and attached to a SC) */ + H1_CS_CLOSING, /* Send pending outgoing data and close the connection ASAP (H1S may be NULL) */ + H1_CS_CLOSED, /* Connection must be closed now and H1C must be released (H1S is NULL) */ + H1_CS_ENTRIES, +} __attribute__((packed)); + + +/**** tiny state decoding functions for debug helpers ****/ + +/* returns a h1c state as an abbreviated 3-letter string, or "???" if unknown */ +static inline const char *h1c_st_to_str(enum h1_cs st) +{ + switch (st) { + case H1_CS_IDLE: return "IDL"; + case H1_CS_EMBRYONIC: return "EMB"; + case H1_CS_UPGRADING: return "UPG"; + case H1_CS_RUNNING: return "RUN"; + case H1_CS_CLOSING: return "CLI"; + case H1_CS_CLOSED: return "CLD"; + default: return "???"; + } +} + #endif /* _HAPROXY_MUX_H1_T_H */ diff --git a/src/mux_h1.c b/src/mux_h1.c index 2d8ef24b77..6fd4836cca 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -39,6 +39,8 @@ struct h1c { struct task *task; /* timeout management task */ uint32_t flags; /* Connection flags: H1C_F_* */ + enum h1_cs state; /* Connection state */ + struct buffer ibuf; /* Input buffer to store data before parsing */ struct buffer obuf; /* Output buffer to store data after reformatting */ @@ -331,7 +333,7 @@ static void h1_trace(enum trace_level level, uint64_t mask, const struct trace_s return; /* Display frontend/backend info by default */ - chunk_appendf(&trace_buf, " : [%c]", ((h1c->flags & H1C_F_IS_BACK) ? 'B' : 'F')); + chunk_appendf(&trace_buf, " : [%c,%s]", ((h1c->flags & H1C_F_IS_BACK) ? 'B' : 'F'), h1c_st_to_str(h1c->state)); /* Display request and response states if h1s is defined */ if (h1s) { @@ -518,6 +520,23 @@ static inline void h1_release_buf(struct h1c *h1c, struct buffer *bptr) } } +/* Returns 1 if the H1 connection is alive (IDLE, EMBRYONIC, RUNNING or + * RUNNING). Ortherwise 0 is returned. + */ +static inline int h1_is_alive(const struct h1c *h1c) +{ + return (h1c->state <= H1_CS_RUNNING); +} + +/* Switch the H1 connection to CLOSING or CLOSED mode, depending on the output + * buffer state and if there is still a H1 stream or not. If there are sill + * pending outgoing data or if there is still a H1 stream, it is set to CLOSING + * state. Otherwise it is set to CLOSED mode. */ +static inline void h1_close(struct h1c *h1c) +{ + h1c->state = ((h1c->h1s || b_data(&h1c->obuf)) ? H1_CS_CLOSING : H1_CS_CLOSED); +} + /* returns the number of streams in use on a connection to figure if it's idle * or not. We rely on H1C_F_ST_IDLE to know if the connection is in-use or * not. This flag is only set when no H1S is attached and when the previous @@ -888,6 +907,7 @@ static int h1_init(struct connection *conn, struct proxy *proxy, struct session h1c->conn = conn; h1c->px = proxy; + h1c->state = H1_CS_IDLE; h1c->flags = H1C_F_ST_IDLE; h1c->errcode = 0; h1c->ibuf = *input;