]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: h3: extract HEADERS parsing in a dedicated function
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 14 Feb 2022 16:13:55 +0000 (17:13 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 15 Feb 2022 16:12:27 +0000 (17:12 +0100)
Move the HEADERS parsing code outside of generic h3_decode_qcs to a new
dedicated function h3_headers_to_htx. The benefit will be visible when
other H3 frames parsing will be implemented such as DATA.

src/h3.c

index e3ee84694b0b99d6d4ec72aee845c19397f0fc1a..8832229850a54ef7a535064cce4d1eb6b80ef543 100644 (file)
--- a/src/h3.c
+++ b/src/h3.c
@@ -93,21 +93,110 @@ static inline size_t h3_decode_frm_header(uint64_t *ftype, uint64_t *flen,
        return hlen;
 }
 
-/* Decode <qcs> remotely initiated bidi-stream. <fin> must be set to indicate
- * that we received the last data of the stream.
- * Returns <0 on error else 0.
+/* Parse from buffer <buf> a H3 HEADERS frame of length <len>. Data are copied
+ * in a local HTX buffer and transfer to the conn-stream layer. <fin> must be
+ * set if this is the last data to transfer from this stream.
+ *
+ * Returns 0 on success else non-zero.
  */
-static int h3_decode_qcs(struct qcs *qcs, int fin, void *ctx)
+static int h3_headers_to_htx(struct qcs *qcs, struct buffer *buf, uint64_t len,
+                             char fin)
 {
-       struct buffer *rxbuf = &qcs->rx.buf;
-       struct h3 *h3 = ctx;
+       struct buffer htx_buf = BUF_NULL;
+       struct buffer *tmp = get_trash_chunk();
        struct htx *htx = NULL;
        struct htx_sl *sl;
-       struct conn_stream *cs;
        struct http_hdr list[global.tune.max_http_hdr];
+       struct conn_stream *cs;
        unsigned int flags = HTX_SL_F_NONE;
+       struct ist meth = IST_NULL, path = IST_NULL;
+       //struct ist scheme = IST_NULL, authority = IST_NULL;
+       struct ist authority = IST_NULL;
        int hdr_idx;
 
+       if (qpack_decode_fs((const unsigned char *)b_head(buf), len, tmp, list) < 0)
+               return 1;
+
+       qc_get_buf(qcs, &htx_buf);
+       BUG_ON(!b_size(&htx_buf));
+       htx = htx_from_buf(&htx_buf);
+
+       /* first treat pseudo-header to build the start line */
+       hdr_idx = 0;
+       while (1) {
+               if (isteq(list[hdr_idx].n, ist("")))
+                       break;
+
+               if (istmatch(list[hdr_idx].n, ist(":"))) {
+                       /* pseudo-header */
+                       if (isteq(list[hdr_idx].n, ist(":method")))
+                               meth = list[hdr_idx].v;
+                       else if (isteq(list[hdr_idx].n, ist(":path")))
+                               path = list[hdr_idx].v;
+                       //else if (isteq(list[hdr_idx].n, ist(":scheme")))
+                       //      scheme = list[hdr_idx].v;
+                       else if (isteq(list[hdr_idx].n, ist(":authority")))
+                               authority = list[hdr_idx].v;
+               }
+
+               ++hdr_idx;
+       }
+
+       flags |= HTX_SL_F_VER_11;
+
+       sl = htx_add_stline(htx, HTX_BLK_REQ_SL, flags, meth, path, ist("HTTP/3.0"));
+       if (!sl)
+               return 1;
+
+       if (fin)
+               sl->flags |= HTX_SL_F_BODYLESS;
+
+       sl->info.req.meth = find_http_meth(meth.ptr, meth.len);
+       BUG_ON(sl->info.req.meth == HTTP_METH_OTHER);
+
+       if (isttest(authority))
+               htx_add_header(htx, ist("host"), authority);
+
+       /* now treat standard headers */
+       hdr_idx = 0;
+       while (1) {
+               if (isteq(list[hdr_idx].n, ist("")))
+                       break;
+
+               if (!istmatch(list[hdr_idx].n, ist(":")))
+                       htx_add_header(htx, list[hdr_idx].n, list[hdr_idx].v);
+
+               ++hdr_idx;
+       }
+
+       htx_add_endof(htx, HTX_BLK_EOH);
+       htx_to_buf(htx, &htx_buf);
+
+       if (fin)
+               htx->flags |= HTX_FL_EOM;
+
+       cs = cs_new(qcs->qcc->conn, qcs->qcc->conn->target);
+       cs->flags |= CS_FL_NOT_FIRST;
+       cs->ctx = qcs;
+       stream_create_from_cs(cs, &htx_buf);
+
+       /* buffer is transferred to conn_stream and set to NULL
+        * except on stream creation error.
+        */
+       b_free(&htx_buf);
+       offer_buffers(NULL, 1);
+
+       return 0;
+}
+
+/* Decode <qcs> remotely initiated bidi-stream. <fin> must be set to indicate
+ * that we received the last data of the stream.
+ * Returns <0 on error else 0.
+ */
+static int h3_decode_qcs(struct qcs *qcs, int fin, void *ctx)
+{
+       struct buffer *rxbuf = &qcs->rx.buf;
+
        h3_debug_printf(stderr, "%s: STREAM ID: %llu\n", __func__, qcs->by_id.key);
        if (!b_data(rxbuf))
                return 0;
@@ -139,88 +228,8 @@ static int h3_decode_qcs(struct qcs *qcs, int fin, void *ctx)
                case H3_FT_DATA:
                        break;
                case H3_FT_HEADERS:
-               {
-                       const unsigned char *buf = (const unsigned char *)b_head(rxbuf);
-                       struct buffer htx_buf = BUF_NULL;
-                       struct buffer *tmp = get_trash_chunk();
-                       struct ist meth = IST_NULL, path = IST_NULL;
-                       //struct ist scheme = IST_NULL, authority = IST_NULL;
-                       struct ist authority = IST_NULL;
-
-                       if (qpack_decode_fs(buf, flen, tmp, list) < 0) {
-                               h3->err = QPACK_DECOMPRESSION_FAILED;
-                               return -1;
-                       }
-
-                       b_alloc(&htx_buf);
-                       htx = htx_from_buf(&htx_buf);
-
-                       /* first treat pseudo-header to build the start line */
-                       hdr_idx = 0;
-                       while (1) {
-                               if (isteq(list[hdr_idx].n, ist("")))
-                                       break;
-
-                               if (istmatch(list[hdr_idx].n, ist(":"))) {
-                                       /* pseudo-header */
-                                       if (isteq(list[hdr_idx].n, ist(":method")))
-                                               meth = list[hdr_idx].v;
-                                       else if (isteq(list[hdr_idx].n, ist(":path")))
-                                               path = list[hdr_idx].v;
-                                       //else if (isteq(list[hdr_idx].n, ist(":scheme")))
-                                       //      scheme = list[hdr_idx].v;
-                                       else if (isteq(list[hdr_idx].n, ist(":authority")))
-                                               authority = list[hdr_idx].v;
-                               }
-
-                               ++hdr_idx;
-                       }
-
-                       flags |= HTX_SL_F_VER_11;
-
-                       sl = htx_add_stline(htx, HTX_BLK_REQ_SL, flags, meth, path, ist("HTTP/3.0"));
-                       if (!sl)
-                               goto fail;
-
-                       if (last_stream_frame)
-                               sl->flags |= HTX_SL_F_BODYLESS;
-
-                       sl->info.req.meth = find_http_meth(meth.ptr, meth.len);
-                       BUG_ON(sl->info.req.meth == HTTP_METH_OTHER);
-
-                       if (isttest(authority))
-                               htx_add_header(htx, ist("host"), authority);
-
-                       /* now treat standard headers */
-                       hdr_idx = 0;
-                       while (1) {
-                               if (isteq(list[hdr_idx].n, ist("")))
-                                       break;
-
-                               if (!istmatch(list[hdr_idx].n, ist(":")))
-                                       htx_add_header(htx, list[hdr_idx].n, list[hdr_idx].v);
-
-                               ++hdr_idx;
-                       }
-
-                       htx_add_endof(htx, HTX_BLK_EOH);
-                       htx_to_buf(htx, &htx_buf);
-
-                       if (last_stream_frame)
-                               htx->flags |= HTX_FL_EOM;
-
-                       cs = cs_new(qcs->qcc->conn, qcs->qcc->conn->target);
-                       cs->flags |= CS_FL_NOT_FIRST;
-                       cs->ctx = qcs;
-                       stream_create_from_cs(cs, &htx_buf);
-
-                       /* buffer is transferred to conn_stream and set to NULL
-                        * except on stream creation error.
-                        */
-                       b_free(&htx_buf);
-
+                       h3_headers_to_htx(qcs, rxbuf, flen, last_stream_frame);
                        break;
-               }
                case H3_FT_PUSH_PROMISE:
                        /* Not supported */
                        break;