blob: 296ff4df55529326fbcece8a28b23a28caa76ecf [file] [log] [blame]
Christopher Fauleta3d2a162018-10-22 08:59:39 +02001/*
2 * include/proto/hx.h
3 * This file defines everything related to 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 _PROTO_HTX_H
23#define _PROTO_HTX_H
24
25#include <common/buf.h>
26#include <common/config.h>
27#include <common/standard.h>
28#include <common/http-hdr.h>
29
30#include <types/h1.h>
31#include <types/htx.h>
32
33extern struct htx htx_empty;
34
35struct htx_blk *htx_defrag(struct htx *htx, struct htx_blk *blk);
36struct htx_blk *htx_add_blk(struct htx *htx, enum htx_blk_type type, uint32_t blksz);
37struct htx_blk *htx_remove_blk(struct htx *htx, struct htx_blk *blk);
38
39struct htx_blk *htx_replace_blk_value(struct htx *htx, struct htx_blk *blk,
40 const struct ist old, const struct ist new);
41struct htx_ret htx_xfer_blks(struct htx *dst, struct htx *src, uint32_t count,
42 enum htx_blk_type mark);
43
44struct htx_blk *htx_replace_reqline(struct htx *htx, struct htx_blk *blk,
45 const union h1_sl sl);
46struct htx_blk *htx_replace_resline(struct htx *htx, struct htx_blk *blk,
47 const union h1_sl sl);
48struct htx_blk *htx_replace_header(struct htx *htx, struct htx_blk *blk,
49 const struct ist name, const struct ist value);
50
51struct htx_blk *htx_add_reqline(struct htx *htx, const union h1_sl sl);
52struct htx_blk *htx_add_resline(struct htx *htx, const union h1_sl sl);
53struct htx_blk *htx_add_header(struct htx *htx, const struct ist name, const struct ist value);
54struct htx_blk *htx_add_all_headers(struct htx *htx, const struct http_hdr *hdrs);
55struct htx_blk *htx_add_pseudo_header(struct htx *htx, enum htx_phdr_type phdr, const struct ist value);
56struct htx_blk *htx_add_endof(struct htx *htx, enum htx_blk_type type);
57struct htx_blk *htx_add_data(struct htx *htx, const struct ist data);
58struct htx_blk *htx_add_trailer(struct htx *htx, const struct ist tlr);
59struct htx_blk *htx_add_oob(struct htx *htx, const struct ist oob);
Christopher Faulet24ed8352018-11-22 11:20:43 +010060struct htx_blk *htx_add_data_before(struct htx *htx, const struct htx_blk *ref, const struct ist data);
Christopher Fauleta3d2a162018-10-22 08:59:39 +020061
Christopher Faulet570d1612018-11-26 11:13:57 +010062int htx_reqline_to_str(const struct htx_sl *sl, struct buffer *chk);
63int htx_stline_to_str(const struct htx_sl *sl, struct buffer *chk);
Christopher Fauleta3d2a162018-10-22 08:59:39 +020064int htx_hdr_to_str(const struct ist n, const struct ist v, struct buffer *chk);
65int htx_data_to_str(const struct ist data, struct buffer *chk, int chunked);
66int htx_trailer_to_str(const struct ist tlr, struct buffer *chk);
67
Christopher Faulet570d1612018-11-26 11:13:57 +010068/* Functions and macros to get parts of the start-line or legnth of these
69 * parts
70 */
71#define HTX_SL_LEN(sl) ((sl)->len[0] + (sl)->len[1] + (sl)->len[2])
72
73#define HTX_SL_P1_LEN(sl) ((sl)->len[0])
74#define HTX_SL_P2_LEN(sl) ((sl)->len[1])
75#define HTX_SL_P3_LEN(sl) ((sl)->len[2])
76#define HTX_SL_P1_PTR(sl) ((sl)->l)
77#define HTX_SL_P2_PTR(sl) (HTX_SL_P1_PTR(sl) + HTX_SL_P1_LEN(sl))
78#define HTX_SL_P3_PTR(sl) (HTX_SL_P2_PTR(sl) + HTX_SL_P2_LEN(sl))
79
80#define HTX_SL_REQ_MLEN(sl) HTX_SL_P1_LEN(sl)
81#define HTX_SL_REQ_ULEN(sl) HTX_SL_P2_LEN(sl)
82#define HTX_SL_REQ_VLEN(sl) HTX_SL_P3_LEN(sl)
83#define HTX_SL_REQ_MPTR(sl) HTX_SL_P1_PTR(sl)
84#define HTX_SL_REQ_UPTR(sl) HTX_SL_P2_PTR(sl)
85#define HTX_SL_REQ_VPTR(sl) HTX_SL_P3_PTR(sl)
86
87#define HTX_SL_RES_VLEN(sl) HTX_SL_P1_LEN(sl)
88#define HTX_SL_RES_CLEN(sl) HTX_SL_P2_LEN(sl)
89#define HTX_SL_RES_RLEN(sl) HTX_SL_P3_LEN(sl)
90#define HTX_SL_RES_VPTR(sl) HTX_SL_P1_PTR(sl)
91#define HTX_SL_RES_CPTR(sl) HTX_SL_P2_PTR(sl)
92#define HTX_SL_RES_RPTR(sl) HTX_SL_P3_PTR(sl)
93
94static inline const struct ist htx_sl_p1(const struct htx_sl *sl)
95{
96 return ist2(HTX_SL_P1_PTR(sl), HTX_SL_P1_LEN(sl));
97}
98
99static inline const struct ist htx_sl_p2(const struct htx_sl *sl)
100{
101 return ist2(HTX_SL_P2_PTR(sl), HTX_SL_P2_LEN(sl));
102}
103
104static inline const struct ist htx_sl_p3(const struct htx_sl *sl)
105{
106 return ist2(HTX_SL_P3_PTR(sl), HTX_SL_P3_LEN(sl));
107}
108
109
110static inline const struct ist htx_sl_req_meth(const struct htx_sl *sl)
111{
112 return htx_sl_p1(sl);
113}
114
115static inline const struct ist htx_sl_req_uri(const struct htx_sl *sl)
116{
117 return htx_sl_p2(sl);
118}
119
120static inline const struct ist htx_sl_req_vsn(const struct htx_sl *sl)
121{
122 return htx_sl_p3(sl);
123}
124
125
126static inline const struct ist htx_sl_res_vsn(const struct htx_sl *sl)
127{
128 return htx_sl_p1(sl);
129}
130
131static inline const struct ist htx_sl_res_code(const struct htx_sl *sl)
132{
133 return htx_sl_p2(sl);
134}
135
136static inline const struct ist htx_sl_res_reason(const struct htx_sl *sl)
137{
138 return htx_sl_p3(sl);
139}
Christopher Fauleta3d2a162018-10-22 08:59:39 +0200140
Christopher Faulet54483df2018-11-26 15:05:52 +0100141/* Returns the HTX start-line if set, otherwise it returns NULL. */
142static inline struct htx_sl *htx_get_stline(struct htx *htx)
143{
144 struct htx_sl *sl = NULL;
145
146 if (htx->sl_off != -1)
147 sl = ((void *)htx->blocks + htx->sl_off);
148
149 return sl;
150}
151
Christopher Fauleta3d2a162018-10-22 08:59:39 +0200152/* Returns the array index of a block given its position <pos> */
153static inline uint32_t htx_pos_to_idx(const struct htx *htx, uint32_t pos)
154{
155 return ((htx->size / sizeof(htx->blocks[0])) - pos - 1);
156}
157
158/* Returns the position of the block <blk> */
159static inline uint32_t htx_get_blk_pos(const struct htx *htx, const struct htx_blk *blk)
160{
161 return (htx->blocks + (htx->size / sizeof(htx->blocks[0])) - blk - 1);
162}
163
164/* Returns the block at the position <pos> */
165static inline struct htx_blk *htx_get_blk(const struct htx *htx, uint32_t pos)
166{
167 return ((struct htx_blk *)(htx->blocks) + htx_pos_to_idx(htx, pos));
168}
169
170/* Returns the type of the block <blk> */
171static inline enum htx_blk_type htx_get_blk_type(const struct htx_blk *blk)
172{
173 return (blk->info >> 28);
174}
175
176/* Returns the pseudo-header type of the block <blk>. If it's not a
177 * pseudo-header, HTX_PHDR_UNKNOWN is returned.
178 */
179static inline enum htx_phdr_type htx_get_blk_phdr(const struct htx_blk *blk)
180{
181 enum htx_blk_type type = htx_get_blk_type(blk);
182 enum htx_phdr_type phdr;
183
184 switch (type) {
185 case HTX_BLK_PHDR:
186 phdr = (blk->info & 0xff);
187 return phdr;
188
189 default:
190 /* Not a pseudo-header */
191 return HTX_PHDR_UNKNOWN;
192 }
193}
194
195/* Returns the size of the block <blk>, depending of its type */
196static inline uint32_t htx_get_blksz(const struct htx_blk *blk)
197{
198 enum htx_blk_type type = htx_get_blk_type(blk);
199
200 switch (type) {
201 case HTX_BLK_HDR:
202 /* name.length + value.length */
203 return ((blk->info & 0xff) + ((blk->info >> 8) & 0xfffff));
204 case HTX_BLK_PHDR:
205 /* value.length */
206 return ((blk->info >> 8) & 0xfffff);
207 default:
208 /* value.length */
209 return (blk->info & 0xfffffff);
210 }
211}
212
213/* Returns the position of the oldest entry (head).
214 *
215 * An signed 32-bits integer is returned to handle -1 case. Blocks position are
216 * store on unsigned 32-bits integer, but it is impossible to have so much
217 * blocks to overflow a 32-bits signed integer !
218 */
219static inline int32_t htx_get_head(const struct htx *htx)
220{
221 if (!htx->used)
222 return -1;
223
224 return (((htx->tail + 1U < htx->used) ? htx->wrap : 0) + htx->tail + 1U - htx->used);
225}
226
227/* Returns the oldest HTX block (head) if the HTX message is not
228 * empty. Otherwise it returns NULL.
229*/
230static inline struct htx_blk *htx_get_head_blk(const struct htx *htx)
231{
232 int32_t head = htx_get_head(htx);
233
234 return ((head == -1) ? NULL : htx_get_blk(htx, head));
235}
236
237/* Returns the type of the oldest HTX block (head) if the HTX message is not
238 * empty. Otherwise it returns HTX_BLK_UNUSED.
239 */
240static inline enum htx_blk_type htx_get_head_type(const struct htx *htx)
241{
242 struct htx_blk *blk = htx_get_head_blk(htx);
243
244 return (blk ? htx_get_blk_type(blk) : HTX_BLK_UNUSED);
245}
246
247/* Returns the position of the newest entry (tail).
248 *
249 * An signed 32-bits integer is returned to handle -1 case. Blocks position are
250 * store on unsigned 32-bits integer, but it is impossible to have so much
251 * blocks to overflow a 32-bits signed integer !
252 */
253static inline int32_t htx_get_tail(const struct htx *htx)
254{
255 return (htx->used ? htx->tail : -1);
256}
257
258/* Returns the newest HTX block (tail) if the HTX message is not
259 * empty. Otherwise it returns NULL.
260*/
261static inline struct htx_blk *htx_get_tail_blk(const struct htx *htx)
262{
263 int32_t tail = htx_get_tail(htx);
264
265 return ((tail == -1) ? NULL : htx_get_blk(htx, tail));
266}
267
268/* Returns the type of the newest HTX block (tail) if the HTX message is not
269 * empty. Otherwise it returns HTX_BLK_UNUSED.
270 */
271static inline enum htx_blk_type htx_get_tail_type(const struct htx *htx)
272{
273 struct htx_blk *blk = htx_get_tail_blk(htx);
274
275 return (blk ? htx_get_blk_type(blk) : HTX_BLK_UNUSED);
276}
277
278/* Returns the position of block immediatly before the one pointed by <pos>. If
279 * the message is empty or if <pos> is the position of the head, -1 returned.
280 *
281 * An signed 32-bits integer is returned to handle -1 case. Blocks position are
282 * store on unsigned 32-bits integer, but it is impossible to have so much
283 * blocks to overflow a 32-bits signed integer !
284 */
285static inline int32_t htx_get_prev(const struct htx *htx, uint32_t pos)
286{
287 int32_t head;
288
289 head = htx_get_head(htx);
290 if (head == -1 || pos == head)
291 return -1;
292 if (!pos)
293 return (htx->wrap - 1);
294 return (pos - 1);
295}
296
Christopher Fauletd16b0a72018-11-22 11:23:23 +0100297/* Returns the HTX block before <blk> in the HTX message <htx>. If <blk> is the
298 * head, NULL returned.
299*/
300static inline struct htx_blk *htx_get_prev_blk(const struct htx *htx,
301 const struct htx_blk *blk)
302{
303 int32_t pos;
304
305 pos = htx_get_prev(htx, htx_get_blk_pos(htx, blk));
306 return ((pos == -1) ? NULL : htx_get_blk(htx, pos));
307}
308
Christopher Fauleta3d2a162018-10-22 08:59:39 +0200309/* Returns the position of block immediatly after the one pointed by <pos>. If
310 * the message is empty or if <pos> is the position of the tail, -1 returned.
311 *
312 * An signed 32-bits integer is returned to handle -1 case. Blocks position are
313 * store on unsigned 32-bits integer, but it is impossible to have so much
314 * blocks to overflow a 32-bits signed integer !
315 */
316static inline int32_t htx_get_next(const struct htx *htx, uint32_t pos)
317{
318 if (!htx->used)
319 return -1;
320
321 if (pos == htx->tail)
322 return -1;
323 pos++;
324 if (pos >= htx->wrap)
325 pos = 0;
326 return pos;
327
328}
Christopher Fauletd16b0a72018-11-22 11:23:23 +0100329
330/* Returns the HTX block after <blk> in the HTX message <htx>. If <blk> is the
331 * tail, NULL returned.
332*/
333static inline struct htx_blk *htx_get_next_blk(const struct htx *htx,
334 const struct htx_blk *blk)
335{
336 int32_t pos;
337
338 pos = htx_get_next(htx, htx_get_blk_pos(htx, blk));
339 return ((pos == -1) ? NULL : htx_get_blk(htx, pos));
340}
341
Christopher Fauleta3d2a162018-10-22 08:59:39 +0200342static inline int32_t htx_find_front(const struct htx *htx)
343{
344 int32_t front, pos;
345 uint32_t addr = 0;
346
347 if (!htx->used)
348 return -1;
349
350 front = -1;
351 for (pos = htx_get_head(htx); pos != -1; pos = htx_get_next(htx, pos)) {
352 struct htx_blk *blk = htx_get_blk(htx, pos);
353 enum htx_blk_type type = htx_get_blk_type(blk);
354
355 if (type != HTX_BLK_UNUSED && blk->addr >= addr) {
356 front = pos;
357 addr = blk->addr;
358 }
359 }
360
361 return front;
362}
363
Christopher Faulet14e88252018-11-22 11:28:18 +0100364/* Returns the HTX block containing data with the <offset>, relatively to the
365 * beginning of the HTX message <htx>. It returns an htx_ret. if the HTX block is
366 * not found, htx_ret.blk is set to NULL. Otherwise, it points to the right HTX
367 * block and htx_ret.ret is set to the remaining offset inside the block.
368 */
369static inline struct htx_ret htx_find_blk(const struct htx *htx, uint32_t offset)
370{
371 int32_t pos;
372
373 for (pos = htx_get_head(htx); pos != -1; pos = htx_get_next(htx, pos)) {
374 struct htx_blk *blk = htx_get_blk(htx, pos);
375 uint32_t sz = htx_get_blksz(blk);
376
377 if (offset < sz)
378 return (struct htx_ret){ .blk = blk, .ret = offset };
379 offset -= sz;
380 }
381
382 return (struct htx_ret){ .blk = NULL };
383}
Christopher Fauleta3d2a162018-10-22 08:59:39 +0200384/* Changes the size of the value. It is the caller responsibility to change the
385 * value itself, make sure there is enough space and update allocated value.
386 */
387static inline void htx_set_blk_value_len(struct htx_blk *blk, uint32_t vlen)
388{
389 enum htx_blk_type type = htx_get_blk_type(blk);
390
391 switch (type) {
392 case HTX_BLK_HDR:
393 case HTX_BLK_PHDR:
394 blk->info = (type << 28) + (vlen << 8) + (blk->info & 0xff);
395 break;
396 case HTX_BLK_REQ_SL:
397 case HTX_BLK_RES_SL:
398 case HTX_BLK_DATA:
399 case HTX_BLK_TLR:
400 case HTX_BLK_OOB:
401 blk->info = (type << 28) + vlen;
402 break;
403 default:
404 /* Unexpected case */
405 break;
406 }
407}
408
409/* Returns the data pointer of the block <blk> */
410static inline void *htx_get_blk_ptr(const struct htx *htx, const struct htx_blk *blk)
411{
412 return ((void *)htx->blocks + blk->addr);
413}
414
415/* Returns the name of the block <blk>, only if it is a header. Otherwise it
416 * returns an empty name.
417 */
418static inline struct ist htx_get_blk_name(const struct htx *htx, const struct htx_blk *blk)
419{
420 enum htx_blk_type type = htx_get_blk_type(blk);
421 struct ist ret;
422
423 switch (type) {
424 case HTX_BLK_HDR:
425 ret.ptr = htx_get_blk_ptr(htx, blk);
426 ret.len = blk->info & 0xff;
427 break;
428
429 default:
430 return ist("");
431 }
432 return ret;
433}
434
Christopher Faulet54483df2018-11-26 15:05:52 +0100435
Christopher Fauleta3d2a162018-10-22 08:59:39 +0200436/* Returns the value of the block <blk>, depending on its type. If there is no
437 * value, an empty one is retruned.
438 */
439static inline struct ist htx_get_blk_value(const struct htx *htx, const struct htx_blk *blk)
440{
441 enum htx_blk_type type = htx_get_blk_type(blk);
442 struct ist ret;
443
444 switch (type) {
445 case HTX_BLK_HDR:
446 ret.ptr = htx_get_blk_ptr(htx, blk) + (blk->info & 0xff);
447 ret.len = (blk->info >> 8) & 0xfffff;
448 break;
449
450 case HTX_BLK_PHDR:
451 ret.ptr = htx_get_blk_ptr(htx, blk);
452 ret.len = (blk->info >> 8) & 0xfffff;
453 break;
454
455 case HTX_BLK_REQ_SL:
456 case HTX_BLK_RES_SL:
457 case HTX_BLK_DATA:
458 case HTX_BLK_TLR:
459 case HTX_BLK_OOB:
460 ret.ptr = htx_get_blk_ptr(htx, blk);
461 ret.len = blk->info & 0xfffffff;
462 break;
463
464 default:
465 return ist("");
466 }
467 return ret;
468}
469
Willy Tarreauc01ed9f2018-11-30 14:29:31 +0100470/* Removes <n> bytes from the beginning of DATA block <blk>. The block's start
471 * address and its length are adjusted, and the htx's total data count is
472 * updated. This is used to mark that part of some data were transfered
473 * from a DATA block without removing this DATA block. No sanity check is
474 * performed, the caller is reponsible for doing this exclusively on DATA
475 * blocks, and never removing more than the block's size.
476 */
477static inline void htx_cut_data_blk(struct htx *htx, struct htx_blk *blk, uint32_t n)
478{
479 blk->addr += n;
480 blk->info -= n;
481 htx->data -= n;
482}
Christopher Fauleta3d2a162018-10-22 08:59:39 +0200483
484/* Returns the space used by metadata in <htx>. */
485static inline uint32_t htx_meta_space(const struct htx *htx)
486{
487 return (htx->used * sizeof(htx->blocks[0]));
488}
489
490/* Returns the space used (data + metadata) in <htx> */
491static inline uint32_t htx_used_space(const struct htx *htx)
492{
493 return (htx->data + htx_meta_space(htx));
494}
495
496/* Returns the free space in <htx> */
497static inline uint32_t htx_free_space(const struct htx *htx)
498{
499 return (htx->size - htx_used_space(htx));
500}
501
502/* Returns the maximum size available to store some data in <htx> if a new block
503 * is reserved.
504 */
505static inline uint32_t htx_free_data_space(const struct htx *htx)
506{
507 uint32_t free = htx_free_space(htx);
508
509 if (free < sizeof(htx->blocks[0]))
510 return 0;
511 return (free - sizeof(htx->blocks[0]));
512}
513
514/* Returns 1 if the message has less than 1/4 of its capacity free, otherwise 0 */
515static inline int htx_almost_full(const struct htx *htx)
516{
517 if (!htx->size || htx_free_space(htx) < htx->size / 4)
518 return 1;
519 return 0;
520}
521
522static inline void htx_reset(struct htx *htx)
523{
524 htx->data = htx->used = htx->tail = htx->wrap = htx->front = 0;
525 htx->extra = 0;
526 htx->flags = HTX_FL_NONE;
Christopher Faulet54483df2018-11-26 15:05:52 +0100527 htx->sl_off = -1;
Christopher Fauleta3d2a162018-10-22 08:59:39 +0200528}
529
530/* Returns an HTX message using the buffer <buf>. */
531static inline struct htx *htx_from_buf(struct buffer *buf)
532{
533 struct htx *htx;
534
535 if (b_is_null(buf))
536 return &htx_empty;
537 htx = (struct htx *)(buf->area);
538 htx->size = buf->size - sizeof(*htx);
539 if (!b_data(buf))
540 htx_reset(htx);
541 return htx;
542}
543
544/* Returns 1 if the message is empty, otherwise it returns 0. */
545static inline int htx_is_empty(const struct htx *htx)
546{
547 return (!htx || !htx->used);
548}
549
550/* Returns 1 if the message is not empty, otherwise it returns 0. */
551static inline int htx_is_not_empty(const struct htx *htx)
552{
553 return (htx && htx->used);
554}
555
556/* For debugging purpose */
557static inline const char *htx_blk_type_str(enum htx_blk_type type)
558{
559 switch (type) {
560 case HTX_BLK_REQ_SL: return "HTX_BLK_REQ_SL";
561 case HTX_BLK_RES_SL: return "HTX_BLK_RES_SL";
562 case HTX_BLK_HDR: return "HTX_BLK_HDR";
563 case HTX_BLK_PHDR: return "HTX_BLK_PHDR";
564 case HTX_BLK_EOH: return "HTX_BLK_EOH";
565 case HTX_BLK_DATA: return "HTX_BLK_DATA";
566 case HTX_BLK_EOD: return "HTX_BLK_EOD";
567 case HTX_BLK_TLR: return "HTX_BLK_TLR";
568 case HTX_BLK_EOM: return "HTX_BLK_EOM";
569 case HTX_BLK_OOB: return "HTX_BLK_OOB";
570 case HTX_BLK_UNUSED: return "HTX_BLK_UNUSED";
571 default: return "HTX_BLK_???";
572 };
573}
574
575static inline const char *htx_blk_phdr_str(enum htx_phdr_type phdr)
576{
577 switch (phdr) {
578 case HTX_PHDR_UNKNOWN: return "HTX_PHDR_UNKNOWN";
579 default: return "HTX_PHDR_???";
580 }
581}
582
583static inline void htx_dump(struct htx *htx)
584{
585 int32_t pos;
586
Willy Tarreaua7280a12018-11-26 19:41:40 +0100587 fprintf(stderr, "htx:%p [ size=%u - data=%u - used=%u - wrap=%s - extra=%llu]\n",
Christopher Fauleta3d2a162018-10-22 08:59:39 +0200588 htx, htx->size, htx->data, htx->used,
589 (!htx->used || htx->tail+1 == htx->wrap) ? "NO" : "YES",
Willy Tarreaua7280a12018-11-26 19:41:40 +0100590 (unsigned long long)htx->extra);
Christopher Fauleta3d2a162018-10-22 08:59:39 +0200591 fprintf(stderr, "\thead=%d - tail=%u - front=%u - wrap=%u\n",
592 htx_get_head(htx), htx->tail, htx->front, htx->wrap);
593
594 for (pos = htx_get_head(htx); pos != -1; pos = htx_get_next(htx, pos)) {
Christopher Faulet570d1612018-11-26 11:13:57 +0100595 struct htx_sl *sl;
Christopher Fauleta3d2a162018-10-22 08:59:39 +0200596 struct htx_blk *blk = htx_get_blk(htx, pos);
597 enum htx_blk_type type = htx_get_blk_type(blk);
598 enum htx_phdr_type phdr = htx_get_blk_phdr(blk);
599 uint32_t sz = htx_get_blksz(blk);
600 struct ist n, v;
601
602 n = htx_get_blk_name(htx, blk);
603 v = htx_get_blk_value(htx, blk);
604
Christopher Faulet570d1612018-11-26 11:13:57 +0100605 if (type == HTX_BLK_REQ_SL || type == HTX_BLK_RES_SL) {
Christopher Fauleta3d2a162018-10-22 08:59:39 +0200606 sl = htx_get_blk_ptr(htx, blk);
607 fprintf(stderr, "\t\t[%u] type=%-17s - size=%-6u - addr=%-6u\t%.*s %.*s %.*s\n",
608 pos, htx_blk_type_str(type), sz, blk->addr,
Christopher Faulet570d1612018-11-26 11:13:57 +0100609 HTX_SL_P1_LEN(sl), HTX_SL_P1_PTR(sl),
610 HTX_SL_P2_LEN(sl), HTX_SL_P2_PTR(sl),
611 HTX_SL_P3_LEN(sl), HTX_SL_P3_PTR(sl));
Christopher Fauleta3d2a162018-10-22 08:59:39 +0200612 }
613 else if (type == HTX_BLK_HDR)
614 fprintf(stderr, "\t\t[%u] type=%-17s - size=%-6u - addr=%-6u\t%.*s: %.*s\n",
615 pos, htx_blk_type_str(type), sz, blk->addr,
616 (int)n.len, n.ptr,
617 (int)v.len, v.ptr);
618
619 else if (type == HTX_BLK_PHDR)
620 fprintf(stderr, "\t\t[%u] type=%-17s - size=%-6u - addr=%-6u\t%.*s\n",
621 pos, htx_blk_phdr_str(phdr), sz, blk->addr,
622 (int)v.len, v.ptr);
623 else
624 fprintf(stderr, "\t\t[%u] type=%-17s - size=%-6u - addr=%-6u%s\n",
625 pos, htx_blk_type_str(type), sz, blk->addr,
626 (!v.len ? "\t<empty>" : ""));
627 }
628 fprintf(stderr, "\n");
629}
630
631#endif /* _PROTO_HTX_H */
632
633/*
634 * Local variables:
635 * c-indent-level: 8
636 * c-basic-offset: 8
637 * End:
638 */