/src/haproxy/include/haproxy/htx-t.h
Line | Count | Source |
1 | | /* |
2 | | * include/haproxy/htx-t.h |
3 | | * This file declares the types and constants used the internal HTTP messages |
4 | | * |
5 | | * Copyright (C) 2018 HAProxy Technologies, Christopher Faulet <cfaulet@haproxy.com> |
6 | | * |
7 | | * This library is free software; you can redistribute it and/or |
8 | | * modify it under the terms of the GNU Lesser General Public |
9 | | * License as published by the Free Software Foundation, version 2.1 |
10 | | * exclusively. |
11 | | * |
12 | | * This library is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | | * Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public |
18 | | * License along with this library; if not, write to the Free Software |
19 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | | */ |
21 | | |
22 | | #ifndef _HAPROXY_HTX_T_H |
23 | | #define _HAPROXY_HTX_T_H |
24 | | |
25 | | #include <haproxy/api.h> |
26 | | #include <haproxy/http-t.h> |
27 | | #include <haproxy/show_flags-t.h> |
28 | | |
29 | | /* |
30 | | * The internal representation of an HTTP message, called HTX, is a structure |
31 | | * with useful information on the message followed by a contiguous array |
32 | | * containing parts of the message, called blocks. A block is composed of |
33 | | * metadata (htx_blk) and the associated payload. Blocks' metadata are stored |
34 | | * starting from the end of the array while their payload are stored at the |
35 | | * beginning. Blocks' metadata are often simply called blocks. it is a misuse of |
36 | | * language that's simplify explanations. |
37 | | * |
38 | | * |
39 | | * +-----+---------------+------------------------------+--------------+ |
40 | | * | HTX | PAYLOADS ==> | | <== HTX_BLKs | |
41 | | * +-----+---------------+------------------------------+--------------+ |
42 | | * ^ |
43 | | * blocks[] (the beginning of the blocks array) |
44 | | * |
45 | | * |
46 | | * The blocks part remains linear and sorted. You may think about it as an array |
47 | | * with negative indexes. But, instead of using negative indexes, we use |
48 | | * positive positions to identify a block. This position is then converted to a |
49 | | * address relatively to the beginning of the blocks array. |
50 | | * |
51 | | * |
52 | | * .....--+------------------------------+-----+-----+ |
53 | | * | ... | BLK | BLK | |
54 | | * .....--+------------------------------+-----+-----+ |
55 | | * ^ ^ |
56 | | * Addr of the block Addr of the block |
57 | | * at the position 1 at the position 0 |
58 | | * |
59 | | * |
60 | | * The payloads part is a raw space that may wrap. You never access to a block's |
61 | | * payload directly. Instead you get a block to retrieve the address of its |
62 | | * payload. When no more space left between blocks and payloads parts, the free |
63 | | * space at the beginning, if any, is used. |
64 | | * |
65 | | * |
66 | | * +----------- WRAPPING ------------------------+ |
67 | | * | | |
68 | | * V | |
69 | | * +-----+-------------+---------------+---------------++--------------+ |
70 | | * | HTX | PAYLOAD ==> | | PAYLOADS ==X || X== HTX_BLKs | |
71 | | * +-----+-------------+---------------+---------------++--------------+ |
72 | | * |
73 | | * |
74 | | * The blocks part, on its side, never wrap. If we have no space to allocate a |
75 | | * new block and if there is a hole at the beginning of the blocks part (so at |
76 | | * the end of the blocks array), we move back all blocks.x |
77 | | * |
78 | | * |
79 | | * ...+--------------+----------+ blocks ...+----------+--------------+ |
80 | | * | X== HTX_BLKS | | defrag | | <== HTX_BLKS | |
81 | | * ...+--------------+----------+ =====> ...+----------+--------------+ |
82 | | * |
83 | | * |
84 | | * At the end, if payload wrapping or blocks defragmentation is not enough, some |
85 | | * free space may be get back with a full defragmentation. This way, the holes in |
86 | | * the middle are not reusable but count in the available free space. The only |
87 | | * way to reuse this lost space is to fully defragment the HTX message. |
88 | | * |
89 | | * - * - |
90 | | * |
91 | | * An HTX block is as well a header as a body part or a trailer. For all these |
92 | | * types of block, a payload is attached to the block. It can also be a mark, |
93 | | * like the end-of-headers or end-of-trailers. For these blocks, there is no |
94 | | * payload but it count for a byte. It is important to not skip it when data are |
95 | | * forwarded. Metadata of an HTX block are composed of 2 fields : |
96 | | * |
97 | | * - .info : It a 32 bits field containing the block's type on 4 bits |
98 | | * followed by the payload length. See below for details. |
99 | | * |
100 | | * - .addr : The payload's address, if any, relatively to the beginning the |
101 | | * array used to store the HTX message itself. |
102 | | * |
103 | | * htx_blk.info representation : |
104 | | * |
105 | | * 0b 0000 0000 0000 0000 0000 0000 0000 0000 |
106 | | * ---- ------------------------ --------- |
107 | | * type value (1 MB max) name length (header/trailer) |
108 | | * ---------------------------------- |
109 | | * data length (256 MB max) |
110 | | * (body, method, path, version, status, reason) |
111 | | * |
112 | | * types : |
113 | | * - 0000 = request start-line |
114 | | * - 0001 = response start-line |
115 | | * - 0010 = header |
116 | | * - 0011 = end-of-headers |
117 | | * - 0100 = data |
118 | | * - 0101 = trailer |
119 | | * - 0110 = end-of-trailers |
120 | | * ... |
121 | | * - 1111 = unused |
122 | | * |
123 | | */ |
124 | | |
125 | | /* HTX start-line flags. |
126 | | * Please also update the se_show_flags() function below in case of changes. |
127 | | */ |
128 | 0 | #define HTX_SL_F_NONE 0x00000000 |
129 | 0 | #define HTX_SL_F_IS_RESP 0x00000001 /* It is the response start-line (unset means the request one) */ |
130 | 0 | #define HTX_SL_F_XFER_LEN 0x00000002 /* The message xfer size can be determined */ |
131 | 0 | #define HTX_SL_F_XFER_ENC 0x00000004 /* The transfer-encoding header was found in message */ |
132 | 0 | #define HTX_SL_F_CLEN 0x00000008 /* The content-length header was found in message */ |
133 | 0 | #define HTX_SL_F_CHNK 0x00000010 /* The message payload is chunked */ |
134 | 0 | #define HTX_SL_F_VER_11 0x00000020 /* The message indicates version 1.1 or above */ |
135 | 0 | #define HTX_SL_F_BODYLESS 0x00000040 /* The message has no body (content-length = 0) */ |
136 | 0 | #define HTX_SL_F_HAS_SCHM 0x00000080 /* The scheme is explicitly specified */ |
137 | 0 | #define HTX_SL_F_SCHM_HTTP 0x00000100 /* The scheme HTTP should be used */ |
138 | 0 | #define HTX_SL_F_SCHM_HTTPS 0x00000200 /* The scheme HTTPS should be used */ |
139 | 0 | #define HTX_SL_F_HAS_AUTHORITY 0x00000400 /* The request authority is explicitly specified */ |
140 | 0 | #define HTX_SL_F_NORMALIZED_URI 0x00000800 /* The received URI is normalized (an implicit absolute-uri form) */ |
141 | 0 | #define HTX_SL_F_CONN_UPG 0x00001000 /* The message contains "connection: upgrade" header */ |
142 | 0 | #define HTX_SL_F_BODYLESS_RESP 0x00002000 /* The response to this message is bodyless (only for request) */ |
143 | 0 | #define HTX_SL_F_NOT_HTTP 0x00004000 /* Not an HTTP message (e.g "RTSP", only possible if invalid message are accepted) */ |
144 | 0 | #define HTX_SL_F_UPG_HDR 0x00008000 /* non-empty Upgrapde header found */ |
145 | | |
146 | | /* This function is used to report flags in debugging tools. Please reflect |
147 | | * below any single-bit flag addition above in the same order via the |
148 | | * __APPEND_FLAG macro. The new end of the buffer is returned. |
149 | | */ |
150 | | static forceinline char *hsl_show_flags(char *buf, size_t len, const char *delim, uint flg) |
151 | 0 | { |
152 | 0 | #define _(f, ...) __APPEND_FLAG(buf, len, delim, flg, f, #f, __VA_ARGS__) |
153 | 0 | /* prologue */ |
154 | 0 | _(0); |
155 | 0 | /* flags */ |
156 | 0 |
|
157 | 0 | _(HTX_SL_F_IS_RESP, _(HTX_SL_F_XFER_LEN, _(HTX_SL_F_XFER_ENC, |
158 | 0 | _(HTX_SL_F_CLEN, _(HTX_SL_F_CHNK, _(HTX_SL_F_VER_11, |
159 | 0 | _(HTX_SL_F_BODYLESS, _(HTX_SL_F_HAS_SCHM, _(HTX_SL_F_SCHM_HTTP, |
160 | 0 | _(HTX_SL_F_SCHM_HTTPS, _(HTX_SL_F_HAS_AUTHORITY, |
161 | 0 | _(HTX_SL_F_NORMALIZED_URI, _(HTX_SL_F_CONN_UPG, _(HTX_SL_F_BODYLESS_RESP, |
162 | 0 | _(HTX_SL_F_NOT_HTTP, _(HTX_SL_F_UPG_HDR)))))))))))))))); |
163 | 0 | /* epilogue */ |
164 | 0 | _(~0U); |
165 | 0 | return buf; |
166 | 0 | #undef _ |
167 | 0 | } Unexecuted instantiation: cfgparse.c:hsl_show_flags Unexecuted instantiation: cli.c:hsl_show_flags Unexecuted instantiation: connection.c:hsl_show_flags Unexecuted instantiation: debug.c:hsl_show_flags Unexecuted instantiation: errors.c:hsl_show_flags Unexecuted instantiation: fd.c:hsl_show_flags Unexecuted instantiation: frontend.c:hsl_show_flags Unexecuted instantiation: haproxy.c:hsl_show_flags Unexecuted instantiation: http_ana.c:hsl_show_flags Unexecuted instantiation: http_ext.c:hsl_show_flags Unexecuted instantiation: http_htx.c:hsl_show_flags Unexecuted instantiation: http_rules.c:hsl_show_flags Unexecuted instantiation: htx.c:hsl_show_flags Unexecuted instantiation: limits.c:hsl_show_flags Unexecuted instantiation: listener.c:hsl_show_flags Unexecuted instantiation: log.c:hsl_show_flags Unexecuted instantiation: mworker.c:hsl_show_flags Unexecuted instantiation: peers.c:hsl_show_flags Unexecuted instantiation: pool.c:hsl_show_flags Unexecuted instantiation: proto_rhttp.c:hsl_show_flags Unexecuted instantiation: proto_sockpair.c:hsl_show_flags Unexecuted instantiation: proxy.c:hsl_show_flags Unexecuted instantiation: queue.c:hsl_show_flags Unexecuted instantiation: resolvers.c:hsl_show_flags Unexecuted instantiation: ring.c:hsl_show_flags Unexecuted instantiation: sample.c:hsl_show_flags Unexecuted instantiation: server.c:hsl_show_flags Unexecuted instantiation: session.c:hsl_show_flags Unexecuted instantiation: sink.c:hsl_show_flags Unexecuted instantiation: sock.c:hsl_show_flags Unexecuted instantiation: stats-html.c:hsl_show_flags Unexecuted instantiation: stats-proxy.c:hsl_show_flags Unexecuted instantiation: stats.c:hsl_show_flags Unexecuted instantiation: stconn.c:hsl_show_flags Unexecuted instantiation: stick_table.c:hsl_show_flags Unexecuted instantiation: stream.c:hsl_show_flags Unexecuted instantiation: tcp_rules.c:hsl_show_flags Unexecuted instantiation: tcpcheck.c:hsl_show_flags Unexecuted instantiation: thread.c:hsl_show_flags Unexecuted instantiation: tools.c:hsl_show_flags Unexecuted instantiation: trace.c:hsl_show_flags Unexecuted instantiation: vars.c:hsl_show_flags Unexecuted instantiation: activity.c:hsl_show_flags Unexecuted instantiation: applet.c:hsl_show_flags Unexecuted instantiation: backend.c:hsl_show_flags Unexecuted instantiation: cfgparse-global.c:hsl_show_flags Unexecuted instantiation: cfgparse-listen.c:hsl_show_flags Unexecuted instantiation: channel.c:hsl_show_flags Unexecuted instantiation: check.c:hsl_show_flags Unexecuted instantiation: compression.c:hsl_show_flags Unexecuted instantiation: dns.c:hsl_show_flags Unexecuted instantiation: dns_ring.c:hsl_show_flags Unexecuted instantiation: extcheck.c:hsl_show_flags Unexecuted instantiation: filters.c:hsl_show_flags Unexecuted instantiation: flt_http_comp.c:hsl_show_flags Unexecuted instantiation: haterm.c:hsl_show_flags Unexecuted instantiation: http_fetch.c:hsl_show_flags Unexecuted instantiation: mux_spop.c:hsl_show_flags Unexecuted instantiation: pattern.c:hsl_show_flags Unexecuted instantiation: payload.c:hsl_show_flags Unexecuted instantiation: proto_tcp.c:hsl_show_flags Unexecuted instantiation: stats-json.c:hsl_show_flags Unexecuted instantiation: cache.c:hsl_show_flags Unexecuted instantiation: fcgi-app.c:hsl_show_flags Unexecuted instantiation: flt_spoe.c:hsl_show_flags Unexecuted instantiation: h1_htx.c:hsl_show_flags |
168 | | |
169 | | /* Overhead induced by HTX on buffers during transfers. In addition to the size |
170 | | * of the HTX structure itself, and meta data for one block, another block is |
171 | | * accounted to favored zero-copy xfer. |
172 | | */ |
173 | 0 | #define HTX_BUF_OVERHEAD (sizeof(struct htx) + 2 * sizeof(struct htx_blk)) |
174 | | |
175 | | /* HTX flags. |
176 | | * Please also update the htx_show_flags() function below in case of changes. |
177 | | */ |
178 | 0 | #define HTX_FL_NONE 0x00000000 |
179 | 0 | #define HTX_FL_PARSING_ERROR 0x00000001 /* Set when a parsing error occurred */ |
180 | 0 | #define HTX_FL_PROCESSING_ERROR 0x00000002 /* Set when a processing error occurred */ |
181 | 0 | #define HTX_FL_FRAGMENTED 0x00000004 /* Set when the HTX buffer is fragmented */ |
182 | 0 | #define HTX_FL_UNORDERED 0x00000008 /* Set when the HTX buffer are not ordered */ |
183 | 0 | #define HTX_FL_EOM 0x00000010 /* Set when end-of-message is reached from the HTTP point of view |
184 | | * (at worst, on the EOM block is missing) |
185 | | */ |
186 | | /* This function is used to report flags in debugging tools. Please reflect |
187 | | * below any single-bit flag addition above in the same order via the |
188 | | * __APPEND_FLAG macro. The new end of the buffer is returned. |
189 | | */ |
190 | | static forceinline char *htx_show_flags(char *buf, size_t len, const char *delim, uint flg) |
191 | 0 | { |
192 | 0 | #define _(f, ...) __APPEND_FLAG(buf, len, delim, flg, f, #f, __VA_ARGS__) |
193 | 0 | /* prologue */ |
194 | 0 | _(0); |
195 | 0 | /* flags */ |
196 | 0 | _(HTX_FL_PARSING_ERROR, _(HTX_FL_PROCESSING_ERROR, |
197 | 0 | _(HTX_FL_FRAGMENTED, _(HTX_FL_UNORDERED, _(HTX_FL_EOM))))); |
198 | 0 | /* epilogue */ |
199 | 0 | _(~0U); |
200 | 0 | return buf; |
201 | 0 | #undef _ |
202 | 0 | } Unexecuted instantiation: cfgparse.c:htx_show_flags Unexecuted instantiation: cli.c:htx_show_flags Unexecuted instantiation: connection.c:htx_show_flags Unexecuted instantiation: debug.c:htx_show_flags Unexecuted instantiation: errors.c:htx_show_flags Unexecuted instantiation: fd.c:htx_show_flags Unexecuted instantiation: frontend.c:htx_show_flags Unexecuted instantiation: haproxy.c:htx_show_flags Unexecuted instantiation: http_ana.c:htx_show_flags Unexecuted instantiation: http_ext.c:htx_show_flags Unexecuted instantiation: http_htx.c:htx_show_flags Unexecuted instantiation: http_rules.c:htx_show_flags Unexecuted instantiation: htx.c:htx_show_flags Unexecuted instantiation: limits.c:htx_show_flags Unexecuted instantiation: listener.c:htx_show_flags Unexecuted instantiation: log.c:htx_show_flags Unexecuted instantiation: mworker.c:htx_show_flags Unexecuted instantiation: peers.c:htx_show_flags Unexecuted instantiation: pool.c:htx_show_flags Unexecuted instantiation: proto_rhttp.c:htx_show_flags Unexecuted instantiation: proto_sockpair.c:htx_show_flags Unexecuted instantiation: proxy.c:htx_show_flags Unexecuted instantiation: queue.c:htx_show_flags Unexecuted instantiation: resolvers.c:htx_show_flags Unexecuted instantiation: ring.c:htx_show_flags Unexecuted instantiation: sample.c:htx_show_flags Unexecuted instantiation: server.c:htx_show_flags Unexecuted instantiation: session.c:htx_show_flags Unexecuted instantiation: sink.c:htx_show_flags Unexecuted instantiation: sock.c:htx_show_flags Unexecuted instantiation: stats-html.c:htx_show_flags Unexecuted instantiation: stats-proxy.c:htx_show_flags Unexecuted instantiation: stats.c:htx_show_flags Unexecuted instantiation: stconn.c:htx_show_flags Unexecuted instantiation: stick_table.c:htx_show_flags Unexecuted instantiation: stream.c:htx_show_flags Unexecuted instantiation: tcp_rules.c:htx_show_flags Unexecuted instantiation: tcpcheck.c:htx_show_flags Unexecuted instantiation: thread.c:htx_show_flags Unexecuted instantiation: tools.c:htx_show_flags Unexecuted instantiation: trace.c:htx_show_flags Unexecuted instantiation: vars.c:htx_show_flags Unexecuted instantiation: activity.c:htx_show_flags Unexecuted instantiation: applet.c:htx_show_flags Unexecuted instantiation: backend.c:htx_show_flags Unexecuted instantiation: cfgparse-global.c:htx_show_flags Unexecuted instantiation: cfgparse-listen.c:htx_show_flags Unexecuted instantiation: channel.c:htx_show_flags Unexecuted instantiation: check.c:htx_show_flags Unexecuted instantiation: compression.c:htx_show_flags Unexecuted instantiation: dns.c:htx_show_flags Unexecuted instantiation: dns_ring.c:htx_show_flags Unexecuted instantiation: extcheck.c:htx_show_flags Unexecuted instantiation: filters.c:htx_show_flags Unexecuted instantiation: flt_http_comp.c:htx_show_flags Unexecuted instantiation: haterm.c:htx_show_flags Unexecuted instantiation: http_fetch.c:htx_show_flags Unexecuted instantiation: mux_spop.c:htx_show_flags Unexecuted instantiation: pattern.c:htx_show_flags Unexecuted instantiation: payload.c:htx_show_flags Unexecuted instantiation: proto_tcp.c:htx_show_flags Unexecuted instantiation: stats-json.c:htx_show_flags Unexecuted instantiation: cache.c:htx_show_flags Unexecuted instantiation: fcgi-app.c:htx_show_flags Unexecuted instantiation: flt_spoe.c:htx_show_flags Unexecuted instantiation: h1_htx.c:htx_show_flags |
203 | | |
204 | | |
205 | | /* HTX block's type (max 15). */ |
206 | | enum htx_blk_type { |
207 | | HTX_BLK_REQ_SL = 0, /* Request start-line */ |
208 | | HTX_BLK_RES_SL = 1, /* Response start-line */ |
209 | | HTX_BLK_HDR = 2, /* header name/value block */ |
210 | | HTX_BLK_EOH = 3, /* end-of-headers block */ |
211 | | HTX_BLK_DATA = 4, /* data block */ |
212 | | HTX_BLK_TLR = 5, /* trailer name/value block */ |
213 | | HTX_BLK_EOT = 6, /* end-of-trailers block */ |
214 | | /* 7 .. 14 unused */ |
215 | | HTX_BLK_UNUSED = 15, /* unused/removed block */ |
216 | | }; |
217 | | |
218 | | /* One HTX block descriptor */ |
219 | | struct htx_blk { |
220 | | uint32_t addr; /* relative storage address of the block's payload */ |
221 | | uint32_t info; /* information about the block (type, length) */ |
222 | | }; |
223 | | |
224 | | /* Composite return value used by some HTX functions */ |
225 | | struct htx_ret { |
226 | | int32_t ret; /* A numerical value */ |
227 | | struct htx_blk *blk; /* An HTX block */ |
228 | | }; |
229 | | |
230 | | /* HTX start-line. This is almost always aligned except in rare cases where |
231 | | * parts of the URI are rewritten, hence the packed attribute. |
232 | | */ |
233 | | struct htx_sl { |
234 | | unsigned int flags; /* HTX_SL_F_* */ |
235 | | union { |
236 | | struct { |
237 | | enum http_meth_t meth; /* method */ |
238 | | } req; |
239 | | struct { |
240 | | uint16_t status; /* status code */ |
241 | | } res; |
242 | | } info; |
243 | | |
244 | | /* XXX 2 bytes unused, must be present to keep the rest aligned |
245 | | * (check with "pahole -C htx_sl" that len[] is aligned in case |
246 | | * of doubt). |
247 | | */ |
248 | | char __pad_1; |
249 | | char __pad_2; |
250 | | |
251 | | unsigned int len[3]; /* length of different parts of the start-line */ |
252 | | char l[VAR_ARRAY]; |
253 | | } __attribute__((packed)); |
254 | | |
255 | | /* Internal representation of an HTTP message */ |
256 | | struct htx { |
257 | | uint32_t size; /* the array size, in bytes, used to store the HTTP message itself */ |
258 | | uint32_t data; /* the data size, in bytes. To known to total size used by all allocated |
259 | | * blocks (blocks and their contents), you need to add size used by blocks, |
260 | | * i.e. [ used * sizeof(struct htx_blk *) ] */ |
261 | | uint32_t hdrs_data; |
262 | | int32_t tail; /* newest inserted block. -1 if the HTX message is empty */ |
263 | | int32_t head; /* oldest inserted block. -1 if the HTX message is empty */ |
264 | | int32_t first; /* position of the first block to (re)start the analyse. -1 if unset. */ |
265 | | |
266 | | uint32_t tail_addr; /* start address of the free space in front of the the blocks table */ |
267 | | uint32_t head_addr; /* start address of the free space at the beginning */ |
268 | | uint32_t end_addr; /* end address of the free space at the beginning */ |
269 | | |
270 | | uint32_t flags; /* HTX_FL_* */ |
271 | | |
272 | | /* Blocks representing the HTTP message itself */ |
273 | | char blocks[VAR_ARRAY] ALIGNED(8); |
274 | | }; |
275 | | |
276 | | #endif /* _HAPROXY_HTX_T_H */ |
277 | | |
278 | | /* |
279 | | * Local variables: |
280 | | * c-indent-level: 8 |
281 | | * c-basic-offset: 8 |
282 | | * End: |
283 | | */ |