blob: e618a202222fe92ebc7069751cdf642b77902c25 [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
141/* Returns the array index of a block given its position <pos> */
142static inline uint32_t htx_pos_to_idx(const struct htx *htx, uint32_t pos)
143{
144 return ((htx->size / sizeof(htx->blocks[0])) - pos - 1);
145}
146
147/* Returns the position of the block <blk> */
148static inline uint32_t htx_get_blk_pos(const struct htx *htx, const struct htx_blk *blk)
149{
150 return (htx->blocks + (htx->size / sizeof(htx->blocks[0])) - blk - 1);
151}
152
153/* Returns the block at the position <pos> */
154static inline struct htx_blk *htx_get_blk(const struct htx *htx, uint32_t pos)
155{
156 return ((struct htx_blk *)(htx->blocks) + htx_pos_to_idx(htx, pos));
157}
158
159/* Returns the type of the block <blk> */
160static inline enum htx_blk_type htx_get_blk_type(const struct htx_blk *blk)
161{
162 return (blk->info >> 28);
163}
164
165/* Returns the pseudo-header type of the block <blk>. If it's not a
166 * pseudo-header, HTX_PHDR_UNKNOWN is returned.
167 */
168static inline enum htx_phdr_type htx_get_blk_phdr(const struct htx_blk *blk)
169{
170 enum htx_blk_type type = htx_get_blk_type(blk);
171 enum htx_phdr_type phdr;
172
173 switch (type) {
174 case HTX_BLK_PHDR:
175 phdr = (blk->info & 0xff);
176 return phdr;
177
178 default:
179 /* Not a pseudo-header */
180 return HTX_PHDR_UNKNOWN;
181 }
182}
183
184/* Returns the size of the block <blk>, depending of its type */
185static inline uint32_t htx_get_blksz(const struct htx_blk *blk)
186{
187 enum htx_blk_type type = htx_get_blk_type(blk);
188
189 switch (type) {
190 case HTX_BLK_HDR:
191 /* name.length + value.length */
192 return ((blk->info & 0xff) + ((blk->info >> 8) & 0xfffff));
193 case HTX_BLK_PHDR:
194 /* value.length */
195 return ((blk->info >> 8) & 0xfffff);
196 default:
197 /* value.length */
198 return (blk->info & 0xfffffff);
199 }
200}
201
202/* Returns the position of the oldest entry (head).
203 *
204 * An signed 32-bits integer is returned to handle -1 case. Blocks position are
205 * store on unsigned 32-bits integer, but it is impossible to have so much
206 * blocks to overflow a 32-bits signed integer !
207 */
208static inline int32_t htx_get_head(const struct htx *htx)
209{
210 if (!htx->used)
211 return -1;
212
213 return (((htx->tail + 1U < htx->used) ? htx->wrap : 0) + htx->tail + 1U - htx->used);
214}
215
216/* Returns the oldest HTX block (head) if the HTX message is not
217 * empty. Otherwise it returns NULL.
218*/
219static inline struct htx_blk *htx_get_head_blk(const struct htx *htx)
220{
221 int32_t head = htx_get_head(htx);
222
223 return ((head == -1) ? NULL : htx_get_blk(htx, head));
224}
225
226/* Returns the type of the oldest HTX block (head) if the HTX message is not
227 * empty. Otherwise it returns HTX_BLK_UNUSED.
228 */
229static inline enum htx_blk_type htx_get_head_type(const struct htx *htx)
230{
231 struct htx_blk *blk = htx_get_head_blk(htx);
232
233 return (blk ? htx_get_blk_type(blk) : HTX_BLK_UNUSED);
234}
235
236/* Returns the position of the newest entry (tail).
237 *
238 * An signed 32-bits integer is returned to handle -1 case. Blocks position are
239 * store on unsigned 32-bits integer, but it is impossible to have so much
240 * blocks to overflow a 32-bits signed integer !
241 */
242static inline int32_t htx_get_tail(const struct htx *htx)
243{
244 return (htx->used ? htx->tail : -1);
245}
246
247/* Returns the newest HTX block (tail) if the HTX message is not
248 * empty. Otherwise it returns NULL.
249*/
250static inline struct htx_blk *htx_get_tail_blk(const struct htx *htx)
251{
252 int32_t tail = htx_get_tail(htx);
253
254 return ((tail == -1) ? NULL : htx_get_blk(htx, tail));
255}
256
257/* Returns the type of the newest HTX block (tail) if the HTX message is not
258 * empty. Otherwise it returns HTX_BLK_UNUSED.
259 */
260static inline enum htx_blk_type htx_get_tail_type(const struct htx *htx)
261{
262 struct htx_blk *blk = htx_get_tail_blk(htx);
263
264 return (blk ? htx_get_blk_type(blk) : HTX_BLK_UNUSED);
265}
266
267/* Returns the position of block immediatly before the one pointed by <pos>. If
268 * the message is empty or if <pos> is the position of the head, -1 returned.
269 *
270 * An signed 32-bits integer is returned to handle -1 case. Blocks position are
271 * store on unsigned 32-bits integer, but it is impossible to have so much
272 * blocks to overflow a 32-bits signed integer !
273 */
274static inline int32_t htx_get_prev(const struct htx *htx, uint32_t pos)
275{
276 int32_t head;
277
278 head = htx_get_head(htx);
279 if (head == -1 || pos == head)
280 return -1;
281 if (!pos)
282 return (htx->wrap - 1);
283 return (pos - 1);
284}
285
Christopher Fauletd16b0a72018-11-22 11:23:23 +0100286/* Returns the HTX block before <blk> in the HTX message <htx>. If <blk> is the
287 * head, NULL returned.
288*/
289static inline struct htx_blk *htx_get_prev_blk(const struct htx *htx,
290 const struct htx_blk *blk)
291{
292 int32_t pos;
293
294 pos = htx_get_prev(htx, htx_get_blk_pos(htx, blk));
295 return ((pos == -1) ? NULL : htx_get_blk(htx, pos));
296}
297
Christopher Fauleta3d2a162018-10-22 08:59:39 +0200298/* Returns the position of block immediatly after the one pointed by <pos>. If
299 * the message is empty or if <pos> is the position of the tail, -1 returned.
300 *
301 * An signed 32-bits integer is returned to handle -1 case. Blocks position are
302 * store on unsigned 32-bits integer, but it is impossible to have so much
303 * blocks to overflow a 32-bits signed integer !
304 */
305static inline int32_t htx_get_next(const struct htx *htx, uint32_t pos)
306{
307 if (!htx->used)
308 return -1;
309
310 if (pos == htx->tail)
311 return -1;
312 pos++;
313 if (pos >= htx->wrap)
314 pos = 0;
315 return pos;
316
317}
Christopher Fauletd16b0a72018-11-22 11:23:23 +0100318
319/* Returns the HTX block after <blk> in the HTX message <htx>. If <blk> is the
320 * tail, NULL returned.
321*/
322static inline struct htx_blk *htx_get_next_blk(const struct htx *htx,
323 const struct htx_blk *blk)
324{
325 int32_t pos;
326
327 pos = htx_get_next(htx, htx_get_blk_pos(htx, blk));
328 return ((pos == -1) ? NULL : htx_get_blk(htx, pos));
329}
330
Christopher Fauleta3d2a162018-10-22 08:59:39 +0200331static inline int32_t htx_find_front(const struct htx *htx)
332{
333 int32_t front, pos;
334 uint32_t addr = 0;
335
336 if (!htx->used)
337 return -1;
338
339 front = -1;
340 for (pos = htx_get_head(htx); pos != -1; pos = htx_get_next(htx, pos)) {
341 struct htx_blk *blk = htx_get_blk(htx, pos);
342 enum htx_blk_type type = htx_get_blk_type(blk);
343
344 if (type != HTX_BLK_UNUSED && blk->addr >= addr) {
345 front = pos;
346 addr = blk->addr;
347 }
348 }
349
350 return front;
351}
352
Christopher Faulet14e88252018-11-22 11:28:18 +0100353/* Returns the HTX block containing data with the <offset>, relatively to the
354 * beginning of the HTX message <htx>. It returns an htx_ret. if the HTX block is
355 * not found, htx_ret.blk is set to NULL. Otherwise, it points to the right HTX
356 * block and htx_ret.ret is set to the remaining offset inside the block.
357 */
358static inline struct htx_ret htx_find_blk(const struct htx *htx, uint32_t offset)
359{
360 int32_t pos;
361
362 for (pos = htx_get_head(htx); pos != -1; pos = htx_get_next(htx, pos)) {
363 struct htx_blk *blk = htx_get_blk(htx, pos);
364 uint32_t sz = htx_get_blksz(blk);
365
366 if (offset < sz)
367 return (struct htx_ret){ .blk = blk, .ret = offset };
368 offset -= sz;
369 }
370
371 return (struct htx_ret){ .blk = NULL };
372}
Christopher Fauleta3d2a162018-10-22 08:59:39 +0200373/* Changes the size of the value. It is the caller responsibility to change the
374 * value itself, make sure there is enough space and update allocated value.
375 */
376static inline void htx_set_blk_value_len(struct htx_blk *blk, uint32_t vlen)
377{
378 enum htx_blk_type type = htx_get_blk_type(blk);
379
380 switch (type) {
381 case HTX_BLK_HDR:
382 case HTX_BLK_PHDR:
383 blk->info = (type << 28) + (vlen << 8) + (blk->info & 0xff);
384 break;
385 case HTX_BLK_REQ_SL:
386 case HTX_BLK_RES_SL:
387 case HTX_BLK_DATA:
388 case HTX_BLK_TLR:
389 case HTX_BLK_OOB:
390 blk->info = (type << 28) + vlen;
391 break;
392 default:
393 /* Unexpected case */
394 break;
395 }
396}
397
398/* Returns the data pointer of the block <blk> */
399static inline void *htx_get_blk_ptr(const struct htx *htx, const struct htx_blk *blk)
400{
401 return ((void *)htx->blocks + blk->addr);
402}
403
404/* Returns the name of the block <blk>, only if it is a header. Otherwise it
405 * returns an empty name.
406 */
407static inline struct ist htx_get_blk_name(const struct htx *htx, const struct htx_blk *blk)
408{
409 enum htx_blk_type type = htx_get_blk_type(blk);
410 struct ist ret;
411
412 switch (type) {
413 case HTX_BLK_HDR:
414 ret.ptr = htx_get_blk_ptr(htx, blk);
415 ret.len = blk->info & 0xff;
416 break;
417
418 default:
419 return ist("");
420 }
421 return ret;
422}
423
424/* Returns the value of the block <blk>, depending on its type. If there is no
425 * value, an empty one is retruned.
426 */
427static inline struct ist htx_get_blk_value(const struct htx *htx, const struct htx_blk *blk)
428{
429 enum htx_blk_type type = htx_get_blk_type(blk);
430 struct ist ret;
431
432 switch (type) {
433 case HTX_BLK_HDR:
434 ret.ptr = htx_get_blk_ptr(htx, blk) + (blk->info & 0xff);
435 ret.len = (blk->info >> 8) & 0xfffff;
436 break;
437
438 case HTX_BLK_PHDR:
439 ret.ptr = htx_get_blk_ptr(htx, blk);
440 ret.len = (blk->info >> 8) & 0xfffff;
441 break;
442
443 case HTX_BLK_REQ_SL:
444 case HTX_BLK_RES_SL:
445 case HTX_BLK_DATA:
446 case HTX_BLK_TLR:
447 case HTX_BLK_OOB:
448 ret.ptr = htx_get_blk_ptr(htx, blk);
449 ret.len = blk->info & 0xfffffff;
450 break;
451
452 default:
453 return ist("");
454 }
455 return ret;
456}
457
Willy Tarreauc01ed9f2018-11-30 14:29:31 +0100458/* Removes <n> bytes from the beginning of DATA block <blk>. The block's start
459 * address and its length are adjusted, and the htx's total data count is
460 * updated. This is used to mark that part of some data were transfered
461 * from a DATA block without removing this DATA block. No sanity check is
462 * performed, the caller is reponsible for doing this exclusively on DATA
463 * blocks, and never removing more than the block's size.
464 */
465static inline void htx_cut_data_blk(struct htx *htx, struct htx_blk *blk, uint32_t n)
466{
467 blk->addr += n;
468 blk->info -= n;
469 htx->data -= n;
470}
Christopher Fauleta3d2a162018-10-22 08:59:39 +0200471
472/* Returns the space used by metadata in <htx>. */
473static inline uint32_t htx_meta_space(const struct htx *htx)
474{
475 return (htx->used * sizeof(htx->blocks[0]));
476}
477
478/* Returns the space used (data + metadata) in <htx> */
479static inline uint32_t htx_used_space(const struct htx *htx)
480{
481 return (htx->data + htx_meta_space(htx));
482}
483
484/* Returns the free space in <htx> */
485static inline uint32_t htx_free_space(const struct htx *htx)
486{
487 return (htx->size - htx_used_space(htx));
488}
489
490/* Returns the maximum size available to store some data in <htx> if a new block
491 * is reserved.
492 */
493static inline uint32_t htx_free_data_space(const struct htx *htx)
494{
495 uint32_t free = htx_free_space(htx);
496
497 if (free < sizeof(htx->blocks[0]))
498 return 0;
499 return (free - sizeof(htx->blocks[0]));
500}
501
502/* Returns 1 if the message has less than 1/4 of its capacity free, otherwise 0 */
503static inline int htx_almost_full(const struct htx *htx)
504{
505 if (!htx->size || htx_free_space(htx) < htx->size / 4)
506 return 1;
507 return 0;
508}
509
510static inline void htx_reset(struct htx *htx)
511{
512 htx->data = htx->used = htx->tail = htx->wrap = htx->front = 0;
513 htx->extra = 0;
514 htx->flags = HTX_FL_NONE;
515}
516
517/* Returns an HTX message using the buffer <buf>. */
518static inline struct htx *htx_from_buf(struct buffer *buf)
519{
520 struct htx *htx;
521
522 if (b_is_null(buf))
523 return &htx_empty;
524 htx = (struct htx *)(buf->area);
525 htx->size = buf->size - sizeof(*htx);
526 if (!b_data(buf))
527 htx_reset(htx);
528 return htx;
529}
530
531/* Returns 1 if the message is empty, otherwise it returns 0. */
532static inline int htx_is_empty(const struct htx *htx)
533{
534 return (!htx || !htx->used);
535}
536
537/* Returns 1 if the message is not empty, otherwise it returns 0. */
538static inline int htx_is_not_empty(const struct htx *htx)
539{
540 return (htx && htx->used);
541}
542
543/* For debugging purpose */
544static inline const char *htx_blk_type_str(enum htx_blk_type type)
545{
546 switch (type) {
547 case HTX_BLK_REQ_SL: return "HTX_BLK_REQ_SL";
548 case HTX_BLK_RES_SL: return "HTX_BLK_RES_SL";
549 case HTX_BLK_HDR: return "HTX_BLK_HDR";
550 case HTX_BLK_PHDR: return "HTX_BLK_PHDR";
551 case HTX_BLK_EOH: return "HTX_BLK_EOH";
552 case HTX_BLK_DATA: return "HTX_BLK_DATA";
553 case HTX_BLK_EOD: return "HTX_BLK_EOD";
554 case HTX_BLK_TLR: return "HTX_BLK_TLR";
555 case HTX_BLK_EOM: return "HTX_BLK_EOM";
556 case HTX_BLK_OOB: return "HTX_BLK_OOB";
557 case HTX_BLK_UNUSED: return "HTX_BLK_UNUSED";
558 default: return "HTX_BLK_???";
559 };
560}
561
562static inline const char *htx_blk_phdr_str(enum htx_phdr_type phdr)
563{
564 switch (phdr) {
565 case HTX_PHDR_UNKNOWN: return "HTX_PHDR_UNKNOWN";
566 default: return "HTX_PHDR_???";
567 }
568}
569
570static inline void htx_dump(struct htx *htx)
571{
572 int32_t pos;
573
Willy Tarreaua7280a12018-11-26 19:41:40 +0100574 fprintf(stderr, "htx:%p [ size=%u - data=%u - used=%u - wrap=%s - extra=%llu]\n",
Christopher Fauleta3d2a162018-10-22 08:59:39 +0200575 htx, htx->size, htx->data, htx->used,
576 (!htx->used || htx->tail+1 == htx->wrap) ? "NO" : "YES",
Willy Tarreaua7280a12018-11-26 19:41:40 +0100577 (unsigned long long)htx->extra);
Christopher Fauleta3d2a162018-10-22 08:59:39 +0200578 fprintf(stderr, "\thead=%d - tail=%u - front=%u - wrap=%u\n",
579 htx_get_head(htx), htx->tail, htx->front, htx->wrap);
580
581 for (pos = htx_get_head(htx); pos != -1; pos = htx_get_next(htx, pos)) {
Christopher Faulet570d1612018-11-26 11:13:57 +0100582 struct htx_sl *sl;
Christopher Fauleta3d2a162018-10-22 08:59:39 +0200583 struct htx_blk *blk = htx_get_blk(htx, pos);
584 enum htx_blk_type type = htx_get_blk_type(blk);
585 enum htx_phdr_type phdr = htx_get_blk_phdr(blk);
586 uint32_t sz = htx_get_blksz(blk);
587 struct ist n, v;
588
589 n = htx_get_blk_name(htx, blk);
590 v = htx_get_blk_value(htx, blk);
591
Christopher Faulet570d1612018-11-26 11:13:57 +0100592 if (type == HTX_BLK_REQ_SL || type == HTX_BLK_RES_SL) {
Christopher Fauleta3d2a162018-10-22 08:59:39 +0200593 sl = htx_get_blk_ptr(htx, blk);
594 fprintf(stderr, "\t\t[%u] type=%-17s - size=%-6u - addr=%-6u\t%.*s %.*s %.*s\n",
595 pos, htx_blk_type_str(type), sz, blk->addr,
Christopher Faulet570d1612018-11-26 11:13:57 +0100596 HTX_SL_P1_LEN(sl), HTX_SL_P1_PTR(sl),
597 HTX_SL_P2_LEN(sl), HTX_SL_P2_PTR(sl),
598 HTX_SL_P3_LEN(sl), HTX_SL_P3_PTR(sl));
Christopher Fauleta3d2a162018-10-22 08:59:39 +0200599 }
600 else if (type == HTX_BLK_HDR)
601 fprintf(stderr, "\t\t[%u] type=%-17s - size=%-6u - addr=%-6u\t%.*s: %.*s\n",
602 pos, htx_blk_type_str(type), sz, blk->addr,
603 (int)n.len, n.ptr,
604 (int)v.len, v.ptr);
605
606 else if (type == HTX_BLK_PHDR)
607 fprintf(stderr, "\t\t[%u] type=%-17s - size=%-6u - addr=%-6u\t%.*s\n",
608 pos, htx_blk_phdr_str(phdr), sz, blk->addr,
609 (int)v.len, v.ptr);
610 else
611 fprintf(stderr, "\t\t[%u] type=%-17s - size=%-6u - addr=%-6u%s\n",
612 pos, htx_blk_type_str(type), sz, blk->addr,
613 (!v.len ? "\t<empty>" : ""));
614 }
615 fprintf(stderr, "\n");
616}
617
618#endif /* _PROTO_HTX_H */
619
620/*
621 * Local variables:
622 * c-indent-level: 8
623 * c-basic-offset: 8
624 * End:
625 */