diff --git a/include/proto/htx.h b/include/proto/htx.h index 3c5c0fa01..e618a2022 100644 --- a/include/proto/htx.h +++ b/include/proto/htx.h @@ -59,12 +59,84 @@ struct htx_blk *htx_add_trailer(struct htx *htx, const struct ist tlr); struct htx_blk *htx_add_oob(struct htx *htx, const struct ist oob); struct htx_blk *htx_add_data_before(struct htx *htx, const struct htx_blk *ref, const struct ist data); -int htx_reqline_to_str(const union htx_sl *sl, struct buffer *chk); -int htx_stline_to_str(const union htx_sl *sl, struct buffer *chk); +int htx_reqline_to_str(const struct htx_sl *sl, struct buffer *chk); +int htx_stline_to_str(const struct htx_sl *sl, struct buffer *chk); int htx_hdr_to_str(const struct ist n, const struct ist v, struct buffer *chk); int htx_data_to_str(const struct ist data, struct buffer *chk, int chunked); int htx_trailer_to_str(const struct ist tlr, struct buffer *chk); +/* Functions and macros to get parts of the start-line or legnth of these + * parts + */ +#define HTX_SL_LEN(sl) ((sl)->len[0] + (sl)->len[1] + (sl)->len[2]) + +#define HTX_SL_P1_LEN(sl) ((sl)->len[0]) +#define HTX_SL_P2_LEN(sl) ((sl)->len[1]) +#define HTX_SL_P3_LEN(sl) ((sl)->len[2]) +#define HTX_SL_P1_PTR(sl) ((sl)->l) +#define HTX_SL_P2_PTR(sl) (HTX_SL_P1_PTR(sl) + HTX_SL_P1_LEN(sl)) +#define HTX_SL_P3_PTR(sl) (HTX_SL_P2_PTR(sl) + HTX_SL_P2_LEN(sl)) + +#define HTX_SL_REQ_MLEN(sl) HTX_SL_P1_LEN(sl) +#define HTX_SL_REQ_ULEN(sl) HTX_SL_P2_LEN(sl) +#define HTX_SL_REQ_VLEN(sl) HTX_SL_P3_LEN(sl) +#define HTX_SL_REQ_MPTR(sl) HTX_SL_P1_PTR(sl) +#define HTX_SL_REQ_UPTR(sl) HTX_SL_P2_PTR(sl) +#define HTX_SL_REQ_VPTR(sl) HTX_SL_P3_PTR(sl) + +#define HTX_SL_RES_VLEN(sl) HTX_SL_P1_LEN(sl) +#define HTX_SL_RES_CLEN(sl) HTX_SL_P2_LEN(sl) +#define HTX_SL_RES_RLEN(sl) HTX_SL_P3_LEN(sl) +#define HTX_SL_RES_VPTR(sl) HTX_SL_P1_PTR(sl) +#define HTX_SL_RES_CPTR(sl) HTX_SL_P2_PTR(sl) +#define HTX_SL_RES_RPTR(sl) HTX_SL_P3_PTR(sl) + +static inline const struct ist htx_sl_p1(const struct htx_sl *sl) +{ + return ist2(HTX_SL_P1_PTR(sl), HTX_SL_P1_LEN(sl)); +} + +static inline const struct ist htx_sl_p2(const struct htx_sl *sl) +{ + return ist2(HTX_SL_P2_PTR(sl), HTX_SL_P2_LEN(sl)); +} + +static inline const struct ist htx_sl_p3(const struct htx_sl *sl) +{ + return ist2(HTX_SL_P3_PTR(sl), HTX_SL_P3_LEN(sl)); +} + + +static inline const struct ist htx_sl_req_meth(const struct htx_sl *sl) +{ + return htx_sl_p1(sl); +} + +static inline const struct ist htx_sl_req_uri(const struct htx_sl *sl) +{ + return htx_sl_p2(sl); +} + +static inline const struct ist htx_sl_req_vsn(const struct htx_sl *sl) +{ + return htx_sl_p3(sl); +} + + +static inline const struct ist htx_sl_res_vsn(const struct htx_sl *sl) +{ + return htx_sl_p1(sl); +} + +static inline const struct ist htx_sl_res_code(const struct htx_sl *sl) +{ + return htx_sl_p2(sl); +} + +static inline const struct ist htx_sl_res_reason(const struct htx_sl *sl) +{ + return htx_sl_p3(sl); +} /* Returns the array index of a block given its position */ static inline uint32_t htx_pos_to_idx(const struct htx *htx, uint32_t pos) @@ -507,7 +579,7 @@ static inline void htx_dump(struct htx *htx) htx_get_head(htx), htx->tail, htx->front, htx->wrap); for (pos = htx_get_head(htx); pos != -1; pos = htx_get_next(htx, pos)) { - union htx_sl *sl; + struct htx_sl *sl; struct htx_blk *blk = htx_get_blk(htx, pos); enum htx_blk_type type = htx_get_blk_type(blk); enum htx_phdr_type phdr = htx_get_blk_phdr(blk); @@ -517,21 +589,13 @@ static inline void htx_dump(struct htx *htx) n = htx_get_blk_name(htx, blk); v = htx_get_blk_value(htx, blk); - if (type == HTX_BLK_REQ_SL) { + if (type == HTX_BLK_REQ_SL || type == HTX_BLK_RES_SL) { sl = htx_get_blk_ptr(htx, blk); fprintf(stderr, "\t\t[%u] type=%-17s - size=%-6u - addr=%-6u\t%.*s %.*s %.*s\n", pos, htx_blk_type_str(type), sz, blk->addr, - (int)sl->rq.m_len, sl->rq.l, - (int)sl->rq.u_len, sl->rq.l + sl->rq.m_len, - (int)sl->rq.v_len, sl->rq.l + sl->rq.m_len + sl->rq.u_len); - } - else if (type == HTX_BLK_RES_SL) { - sl = htx_get_blk_ptr(htx, blk); - fprintf(stderr, "\t\t[%u] type=%-17s - size=%-6u - addr=%-6u\t%.*s %.*s %.*s\n", - pos, htx_blk_type_str(type), sz, blk->addr, - (int)sl->st.v_len, sl->st.l, - (int)sl->st.c_len, sl->st.l + sl->st.v_len, - (int)sl->st.r_len, sl->st.l + sl->rq.v_len + sl->st.c_len); + HTX_SL_P1_LEN(sl), HTX_SL_P1_PTR(sl), + HTX_SL_P2_LEN(sl), HTX_SL_P2_PTR(sl), + HTX_SL_P3_LEN(sl), HTX_SL_P3_PTR(sl)); } else if (type == HTX_BLK_HDR) fprintf(stderr, "\t\t[%u] type=%-17s - size=%-6u - addr=%-6u\t%.*s: %.*s\n", diff --git a/include/types/htx.h b/include/types/htx.h index 8f3280fa0..c70961971 100644 --- a/include/types/htx.h +++ b/include/types/htx.h @@ -73,6 +73,15 @@ * */ +/*HTX start-line flags */ +#define HTX_SL_F_NONE 0x00000000 +#define HTX_SL_F_IS_RESP 0x00000001 /* It is the response start-line (unset means the request one) */ +#define HTX_SL_F_XFER_LEN 0x00000002 /* The message xfer size can be dertermined */ +#define HTX_SL_F_XFER_ENC 0x00000004 /* The transfer-encoding header was found in message */ +#define HTX_SL_F_CLEN 0x00000008 /* The content-length header was found in message */ +#define HTX_SL_F_CHNK 0x00000010 /* The message payload is chunked */ +#define HTX_SL_F_VER_11 0x00000020 /* The message indicates version 1.1 or above */ + /* HTX flags */ #define HTX_FL_NONE 0x00000000 #define HTX_FL_PARSING_ERROR 0x00000001 @@ -111,21 +120,21 @@ struct htx_ret { struct htx_blk *blk; }; -union htx_sl { - struct { - enum http_meth_t meth; /* method */ - int m_len; /* METHOD length */ - int u_len; /* URI length */ - int v_len; /* VERSION length */ - char l[0]; - } rq; /* request line : field, length, data */ - struct { - uint16_t status; /* status code */ - int v_len; /* VERSION length */ - int c_len; /* CODE length */ - int r_len; /* REASON length */ - char l[0]; - } st; /* status line : field, length, data */ +struct htx_sl { + unsigned int flags; /* HTX_SL_F_* */ + union { + struct { + enum http_meth_t meth; /* method */ + } req; + struct { + uint16_t status; /* status code */ + } res; + } info; + + /* XXX 2 bytes unused */ + + unsigned int len[3]; /* length of differnt parts of the start-line */ + char l[0]; }; /* Internal representation of an HTTP message */ diff --git a/src/http_htx.c b/src/http_htx.c index c3027f948..1a8e5bb9e 100644 --- a/src/http_htx.c +++ b/src/http_htx.c @@ -22,7 +22,7 @@ */ union h1_sl http_find_stline(const struct htx *htx) { - union htx_sl *htx_sl; + struct htx_sl *htx_sl; union h1_sl sl; int32_t pos; @@ -32,19 +32,19 @@ union h1_sl http_find_stline(const struct htx *htx) if (type == HTX_BLK_REQ_SL) { htx_sl = htx_get_blk_ptr(htx, blk); - sl.rq.meth = htx_sl->rq.meth; - sl.rq.m = ist2(htx_sl->rq.l, htx_sl->rq.m_len); - sl.rq.u = ist2(htx_sl->rq.l + htx_sl->rq.m_len, htx_sl->rq.u_len); - sl.rq.v = ist2(htx_sl->rq.l + htx_sl->rq.m_len + htx_sl->rq.u_len, htx_sl->rq.v_len); + sl.rq.meth = htx_sl->info.req.meth; + sl.rq.m = htx_sl_req_meth(htx_sl); + sl.rq.u = htx_sl_req_uri(htx_sl); + sl.rq.v = htx_sl_req_vsn(htx_sl); return sl; } if (type == HTX_BLK_RES_SL) { htx_sl = htx_get_blk_ptr(htx, blk); - sl.st.status = htx_sl->st.status; - sl.st.v = ist2(htx_sl->st.l, htx_sl->st.v_len); - sl.st.c = ist2(htx_sl->st.l + htx_sl->st.v_len, htx_sl->st.c_len); - sl.st.r = ist2(htx_sl->st.l + htx_sl->st.v_len + htx_sl->st.c_len, htx_sl->st.r_len); + sl.st.status = htx_sl->info.res.status; + sl.st.v = htx_sl_res_vsn(htx_sl); + sl.st.c = htx_sl_res_code(htx_sl); + sl.st.r = htx_sl_res_reason(htx_sl); return sl; } diff --git a/src/htx.c b/src/htx.c index 0c9646739..85118cf4b 100644 --- a/src/htx.c +++ b/src/htx.c @@ -573,35 +573,35 @@ struct htx_blk *htx_replace_header(struct htx *htx, struct htx_blk *blk, static void htx_set_blk_reqline(struct htx *htx, struct htx_blk *blk, const union h1_sl sl) { - union htx_sl *htx_sl; + struct htx_sl *htx_sl; htx_sl = htx_get_blk_ptr(htx, blk); - htx_sl->rq.meth = sl.rq.meth; + htx_sl->info.req.meth = sl.rq.meth; - htx_sl->rq.m_len = sl.rq.m.len; - htx_sl->rq.u_len = sl.rq.u.len; - htx_sl->rq.v_len = sl.rq.v.len; + HTX_SL_REQ_MLEN(htx_sl) = sl.rq.m.len; + HTX_SL_REQ_ULEN(htx_sl) = sl.rq.u.len; + HTX_SL_REQ_VLEN(htx_sl) = sl.rq.v.len; - memcpy(htx_sl->rq.l, sl.rq.m.ptr, sl.rq.m.len); - memcpy(htx_sl->rq.l + sl.rq.m.len, sl.rq.u.ptr, sl.rq.u.len); - memcpy(htx_sl->rq.l + sl.rq.m.len + sl.rq.u.len, sl.rq.v.ptr, sl.rq.v.len); + memcpy(HTX_SL_REQ_MPTR(htx_sl), sl.rq.m.ptr, sl.rq.m.len); + memcpy(HTX_SL_REQ_UPTR(htx_sl), sl.rq.u.ptr, sl.rq.u.len); + memcpy(HTX_SL_REQ_VPTR(htx_sl), sl.rq.v.ptr, sl.rq.v.len); } static void htx_set_blk_resline(struct htx *htx, struct htx_blk *blk, const union h1_sl sl) { - union htx_sl *htx_sl; + struct htx_sl *htx_sl; htx_sl = htx_get_blk_ptr(htx, blk); - htx_sl->st.status = sl.st.status; + htx_sl->info.res.status = sl.st.status; - htx_sl->st.v_len = sl.st.v.len; - htx_sl->st.c_len = sl.st.c.len; - htx_sl->st.r_len = sl.st.r.len; + HTX_SL_RES_VLEN(htx_sl) = sl.st.v.len; + HTX_SL_RES_CLEN(htx_sl) = sl.st.c.len; + HTX_SL_RES_RLEN(htx_sl) = sl.st.r.len; - memcpy(htx_sl->st.l, sl.st.v.ptr, sl.st.v.len); - memcpy(htx_sl->st.l + sl.st.v.len, sl.st.c.ptr, sl.st.c.len); - memcpy(htx_sl->st.l + sl.st.v.len + sl.st.c.len, sl.st.r.ptr, sl.st.r.len); + memcpy(HTX_SL_RES_VPTR(htx_sl), sl.st.v.ptr, sl.st.v.len); + memcpy(HTX_SL_RES_CPTR(htx_sl), sl.st.c.ptr, sl.st.c.len); + memcpy(HTX_SL_RES_RPTR(htx_sl), sl.st.r.ptr, sl.st.r.len); } /* Replaces the request start line a new one. It returns the new block on @@ -617,7 +617,7 @@ struct htx_blk *htx_replace_reqline(struct htx *htx, struct htx_blk *blk, if (type != HTX_BLK_REQ_SL) return NULL; - size = sizeof(union htx_sl) + sl.rq.m.len + sl.rq.u.len + sl.rq.v.len; + size = sizeof(struct htx_sl) + sl.rq.m.len + sl.rq.u.len + sl.rq.v.len; blk = htx_new_blk_value(htx, blk, size); if (!blk) return NULL; @@ -640,7 +640,7 @@ struct htx_blk *htx_replace_resline(struct htx *htx, struct htx_blk *blk, if (type != HTX_BLK_RES_SL) return NULL; - size = sizeof(union htx_sl) + sl.rq.m.len + sl.rq.u.len + sl.rq.v.len; + size = sizeof(struct htx_sl) + sl.rq.m.len + sl.rq.u.len + sl.rq.v.len; blk = htx_new_blk_value(htx, blk, size); if (!blk) return NULL; @@ -659,7 +659,7 @@ struct htx_blk *htx_add_reqline(struct htx *htx, const union h1_sl sl) struct htx_blk *blk; uint32_t size; - size = sizeof(union htx_sl) + sl.rq.m.len + sl.rq.u.len + sl.rq.v.len; + size = sizeof(struct htx_sl) + sl.rq.m.len + sl.rq.u.len + sl.rq.v.len; /* FIXME: check size (< 256MB) */ blk = htx_add_blk(htx, HTX_BLK_REQ_SL, size); @@ -679,7 +679,7 @@ struct htx_blk *htx_add_resline(struct htx *htx, const union h1_sl sl) struct htx_blk *blk; uint32_t size; - size = sizeof(union htx_sl) + sl.st.v.len + sl.st.c.len + sl.st.r.len; + size = sizeof(struct htx_sl) + sl.st.v.len + sl.st.c.len + sl.st.r.len; /* FIXME: check size (< 256MB) */ blk = htx_add_blk(htx, HTX_BLK_RES_SL, size); @@ -824,16 +824,16 @@ struct htx_blk *htx_add_data_before(struct htx *htx, const struct htx_blk *ref, * chunk . It returns 1 if data are successfully appended, otherwise it * returns 0. */ -int htx_reqline_to_str(const union htx_sl *sl, struct buffer *chk) +int htx_reqline_to_str(const struct htx_sl *sl, struct buffer *chk) { - if (sl->rq.m_len + sl->rq.u_len + sl->rq.v_len + 4 > b_room(chk)) + if (HTX_SL_LEN(sl) + 4 > b_room(chk)) return 0; - chunk_memcat(chk, sl->rq.l, sl->rq.m_len); + chunk_memcat(chk, HTX_SL_REQ_MPTR(sl), HTX_SL_REQ_MLEN(sl)); chunk_memcat(chk, " ", 1); - chunk_memcat(chk, sl->rq.l + sl->rq.m_len, sl->rq.u_len); + chunk_memcat(chk, HTX_SL_REQ_UPTR(sl), HTX_SL_REQ_ULEN(sl)); chunk_memcat(chk, " ", 1); - chunk_memcat(chk, sl->rq.l + sl->rq.m_len + sl->rq.u_len, sl->rq.v_len); + chunk_memcat(chk, HTX_SL_REQ_VPTR(sl), HTX_SL_REQ_VLEN(sl)); chunk_memcat(chk, "\r\n", 2); return 1; @@ -843,16 +843,16 @@ int htx_reqline_to_str(const union htx_sl *sl, struct buffer *chk) * . It returns 1 if data are successfully appended, otherwise it * returns 0. */ -int htx_stline_to_str(const union htx_sl *sl, struct buffer *chk) +int htx_stline_to_str(const struct htx_sl *sl, struct buffer *chk) { - if (sl->st.v_len + sl->st.c_len + sl->st.r_len + 4 > b_size(chk)) + if (HTX_SL_LEN(sl) + 4 > b_size(chk)) return 0; - chunk_memcat(chk, sl->st.l, sl->st.v_len); + chunk_memcat(chk, HTX_SL_RES_VPTR(sl), HTX_SL_RES_VLEN(sl)); chunk_memcat(chk, " ", 1); - chunk_memcat(chk, sl->st.l + sl->st.v_len, sl->st.c_len); + chunk_memcat(chk, HTX_SL_RES_CPTR(sl), HTX_SL_RES_CLEN(sl)); chunk_memcat(chk, " ", 1); - chunk_memcat(chk, sl->st.l + sl->st.v_len + sl->st.c_len, sl->st.r_len); + chunk_memcat(chk, HTX_SL_RES_RPTR(sl), HTX_SL_RES_RLEN(sl)); chunk_memcat(chk, "\r\n", 2); return 1; diff --git a/src/mux_h1.c b/src/mux_h1.c index 4d9db7fba..37c0f8883 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -432,11 +432,11 @@ static void h1_release(struct connection *conn) /* Parse the request version and set H1_MF_VER_11 on if the version is * greater or equal to 1.1 */ -static void h1_parse_req_vsn(struct h1m *h1m, const union htx_sl *sl) +static void h1_parse_req_vsn(struct h1m *h1m, const struct htx_sl *sl) { - const char *p = sl->rq.l + sl->rq.m_len + sl->rq.u_len; + const char *p = HTX_SL_REQ_VPTR(sl); - if ((sl->rq.v_len == 8) && + if ((HTX_SL_REQ_VLEN(sl) == 8) && (*(p + 5) > '1' || (*(p + 5) == '1' && *(p + 7) >= '1'))) h1m->flags |= H1_MF_VER_11; @@ -445,11 +445,11 @@ static void h1_parse_req_vsn(struct h1m *h1m, const union htx_sl *sl) /* Parse the response version and set H1_MF_VER_11 on if the version is * greater or equal to 1.1 */ -static void h1_parse_res_vsn(struct h1m *h1m, const union htx_sl *sl) +static void h1_parse_res_vsn(struct h1m *h1m, const struct htx_sl *sl) { - const char *p = sl->rq.l; + const char *p = HTX_SL_RES_VPTR(sl); - if ((sl->st.v_len == 8) && + if ((HTX_SL_RES_VLEN(sl) == 8) && (*(p + 5) > '1' || (*(p + 5) == '1' && *(p + 7) >= '1'))) h1m->flags |= H1_MF_VER_11; @@ -1205,7 +1205,7 @@ static size_t h1_process_output(struct h1c *h1c, struct buffer *buf, size_t coun blk = htx_get_head_blk(chn_htx); while (!(h1s->flags & errflag) && blk) { - union htx_sl *sl; + struct htx_sl *sl; struct ist n, v; uint32_t sz = htx_get_blksz(blk); @@ -1220,7 +1220,7 @@ static size_t h1_process_output(struct h1c *h1c, struct buffer *buf, size_t coun h1m_init_req(h1m); h1m->flags |= H1_MF_NO_PHDR; sl = htx_get_blk_ptr(chn_htx, blk); - h1s->meth = sl->rq.meth; + h1s->meth = sl->info.req.meth; h1_parse_req_vsn(h1m, sl); if (!htx_reqline_to_str(sl, tmp)) goto copy; @@ -1232,7 +1232,7 @@ static size_t h1_process_output(struct h1c *h1c, struct buffer *buf, size_t coun h1m_init_res(h1m); h1m->flags |= H1_MF_NO_PHDR; sl = htx_get_blk_ptr(chn_htx, blk); - h1s->status = sl->st.status; + h1s->status = sl->info.res.status; h1_parse_res_vsn(h1m, sl); if (!htx_stline_to_str(sl, tmp)) goto copy;