]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: mux-h1: Add a dedicated enum to deal with H1 connection state
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 4 Oct 2022 15:13:32 +0000 (17:13 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 17 Nov 2022 13:33:14 +0000 (14:33 +0100)
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.

include/haproxy/mux_h1-t.h
src/mux_h1.c

index dcc547ab618c7efbf647c7e67daf70bd5c508377..abe5cb87b455bcc1056d3e2719a5bb5492cecf7c 100644 (file)
@@ -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 */
index 2d8ef24b772c4de61a83f7ab0796be305e6d0d88..6fd4836cca23368dd22212e6e12114df7c961e2a 100644 (file)
@@ -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;