30
30
31
31
#include "hpack_tbl.h"
32
32
33
+ /**
34
+ * There are to cases when we allocate space for header:
35
+ * - it->rspace is equal to zero. In this case we allocate
36
+ * `len` bytes;
37
+ * - it->rspace is not equal to zero. This means that we
38
+ * already have buffer with rspace bytes available.
39
+ * If this buffer is rather big to contains the whole
40
+ * header or it is greater then sizeof(TfwStr) we use
41
+ * it. (Save delta = len - it->rspace bytes. Later when
42
+ * `it->rspace` will be exceeded we use it to allocate
43
+ * new chunk).
44
+ * Otherwise allocate new buffer (if we have some free
45
+ * bytes in old buffer, but is is not enough for the
46
+ * new header and is less then sizeof(TfwStr)), we allocate
47
+ * new buffer to prevent extra header chunking.
48
+ */
49
+ #define BUFFER_GET (len , it ) \
50
+ do { \
51
+ \
52
+ \
53
+ BUG_ON(!(len)); \
54
+ if (!(it)->rspace || \
55
+ (len > (it)->rspace && (it)->rspace < sizeof(TfwStr))) \
56
+ { \
57
+ (it)->rspace = len; \
58
+ (it)->pos = tfw_pool_alloc_not_align((it)->pool, len); \
59
+ T_DBG3("%s: get buffer, len=%lu, it->pos=[%p]," \
60
+ " it->pos=%lu\n", __func__, (unsigned long)len, \
61
+ (it)->pos, (unsigned long)(it)->pos); \
62
+ } else { \
63
+ (it)->to_alloc = len > (it)->rspace ? \
64
+ len - (it)->rspace : 0; \
65
+ } \
66
+ } while (0)
67
+
33
68
#define HP_HDR_NAME (name ) \
34
69
(&(TfwStr){ \
35
70
.chunks = &(TfwStr){ \
@@ -278,25 +313,32 @@ do { \
278
313
last - src); \
279
314
} while (0)
280
315
281
- #define BUFFER_HDR_INIT (length , it ) \
316
+ #define BUFFER_HDR_INIT (it ) \
282
317
do { \
283
318
(it)->hdr.data = (it)->pos; \
284
- (it)->hdr.len = length ; \
319
+ (it)->hdr.len = 0 ; \
285
320
(it)->next = 0; \
286
321
} while (0)
287
322
288
323
#define BUFFER_NAME_OPEN (length ) \
289
324
do { \
290
325
WARN_ON_ONCE(!TFW_STR_EMPTY(&it->hdr)); \
291
326
if (state & HPACK_FLAGS_HUFFMAN_NAME) { \
327
+ /* \
328
+ * Allocate extra 50% bytes. Huffman usually \
329
+ * gives compression benefit about 20 - 60 %. \
330
+ * Since we use extra allocated bytes for the \
331
+ * next header, we can allocate extra 50% bytes \
332
+ * without fear of losing a lot of memory. \
333
+ */ \
292
334
unsigned long len = length + (length >> 1 ); \
293
335
\
294
336
BUFFER_GET (len , it ); \
295
337
if (!it -> pos ) { \
296
338
r = - ENOMEM ; \
297
339
goto out ; \
298
340
} \
299
- BUFFER_HDR_INIT(len, it); \
341
+ BUFFER_HDR_INIT (it ); \
300
342
} \
301
343
} while (0 )
302
344
@@ -308,6 +350,13 @@ do { \
308
350
? it->parsed_hdr->nchunks \
309
351
: 1; \
310
352
if (state & HPACK_FLAGS_HUFFMAN_VALUE) { \
353
+ /* \
354
+ * Allocate extra 50% bytes. Huffman usually \
355
+ * gives compression benefit about 20 - 60 %. \
356
+ * Since we use extra allocated bytes for the \
357
+ * next header, we can allocate extra 50% bytes \
358
+ * without fear of losing a lot of memory. \
359
+ */ \
311
360
unsigned long len = length + (length >> 1 ); \
312
361
\
313
362
BUFFER_GET (len , it ); \
@@ -316,13 +365,12 @@ do { \
316
365
goto out ; \
317
366
} \
318
367
if (!TFW_STR_EMPTY (& it -> hdr )) { \
319
- r = tfw_hpack_exp_hdr(req->pool, len, \
320
- it); \
368
+ r = tfw_hpack_exp_hdr (req -> pool , 0 , it ); \
321
369
if (unlikely (r )) \
322
370
return r ; \
323
371
it -> next = it -> hdr .nchunks - 1 ; \
324
372
} else { \
325
- BUFFER_HDR_INIT(length, it); \
373
+ BUFFER_HDR_INIT (it ); \
326
374
} \
327
375
} \
328
376
} while (0 )
@@ -460,41 +508,61 @@ static inline int
460
508
tfw_hpack_huffman_write (char sym , TfwHttpReq * __restrict req )
461
509
{
462
510
TfwMsgParseIter * it = & req -> pit ;
511
+ unsigned long to_alloc ;
463
512
bool np ;
464
513
int r ;
465
514
515
+ #define ADJUST_HDR_LEN (it ) \
516
+ do { \
517
+ TfwStr *hdr = &it->hdr; \
518
+ TfwStr *last = TFW_STR_LAST(hdr); \
519
+ \
520
+ T_DBG3("%s: add to hdr, hdr->len=%lu, last->len=%lu," \
521
+ " last->data=%.*s\n", __func__, hdr->len, last->len, \
522
+ (int)last->len, last->data); \
523
+ \
524
+ ++hdr->len; \
525
+ if (!TFW_STR_PLAIN(hdr)) \
526
+ ++last->len; \
527
+ } while (0)
528
+
466
529
if (it -> rspace ) {
467
530
-- it -> rspace ;
468
531
* it -> pos ++ = sym ;
532
+ ADJUST_HDR_LEN (it );
469
533
return 0 ;
470
534
}
471
535
472
- if (!(it -> pos = tfw_pool_alloc_not_align_np (it -> pool , 1 , & np )))
473
- return - ENOMEM ;
536
+ to_alloc = it -> to_alloc ? it -> to_alloc : 1 ;
537
+ if (to_alloc > 1 )
538
+ it -> rspace = to_alloc - 1 ;
474
539
475
- * it -> pos = sym ;
540
+ it -> pos = tfw_pool_alloc_not_align_np (it -> pool , to_alloc , & np );
541
+ if (!it -> pos )
542
+ return - ENOMEM ;
476
543
477
544
T_DBG3 ("%s: it->rspace=%lu, sym=%c, np=%d\n" , __func__ ,
478
545
it -> rspace , sym , np );
479
546
480
- if (!np ) {
481
- TfwStr * hdr = & it -> hdr ;
482
- TfwStr * last = TFW_STR_LAST (hdr );
483
-
484
- T_DBG3 ("%s: add to hdr, hdr->len=%lu, last->len=%lu,"
485
- " last->data=%.*s\n" , __func__ , hdr -> len , last -> len ,
486
- (int )last -> len , last -> data );
487
-
488
- ++ hdr -> len ;
489
- if (!TFW_STR_PLAIN (hdr ))
490
- ++ last -> len ;
547
+ /*
548
+ * If the new page was allocated or it->pos points to
549
+ * the buffer, which was allocated to store previously
550
+ * decoded header (it->to_alloc != 0) we should expand
551
+ * header.
552
+ */
553
+ if (!np && !it -> to_alloc ) {
554
+ * it -> pos ++ = sym ;
555
+ ADJUST_HDR_LEN (it );
491
556
return 0 ;
492
557
}
493
558
494
559
r = tfw_hpack_exp_hdr (req -> pool , 1 , it );
495
560
if (unlikely (r ))
496
561
return r ;
497
562
563
+ * it -> pos ++ = sym ;
564
+ it -> to_alloc = 0 ;
565
+
498
566
return 0 ;
499
567
}
500
568
@@ -506,28 +574,14 @@ huffman_decode_tail(TfwHPack *__restrict hp, TfwHttpReq *__restrict req,
506
574
unsigned int i ;
507
575
int r ;
508
576
509
- #define ADJUST_EXTRA_RSPACE (req ) \
510
- do { \
511
- TfwMsgParseIter *it = &req->pit; \
512
- TfwStr *hdr = &it->hdr; \
513
- TfwStr *last = TFW_STR_LAST(hdr); \
514
- \
515
- hdr->len -= it->rspace; \
516
- if (!TFW_STR_PLAIN(hdr)) \
517
- last->len -= it->rspace; \
518
- it->rspace = 0; \
519
- } while (0)
520
-
521
577
for (;;) {
522
578
int shift ;
523
579
524
580
if (hp -> curr == - HT_NBITS ) {
525
- if (likely (offset == 0 )) {
526
- ADJUST_EXTRA_RSPACE (req );
581
+ if (likely (offset == 0 ))
527
582
return T_OK ;
528
- } else {
583
+ else
529
584
return T_COMPRESSION ;
530
- }
531
585
}
532
586
533
587
i = (hp -> hctx << - hp -> curr ) & HT_NMASK ;
@@ -554,10 +608,8 @@ do { \
554
608
*/
555
609
if (likely (offset == 0 )) {
556
610
if ((i ^ (HT_EOS_HIGH >> 1 )) <
557
- (1U << - hp -> curr )) {
558
- ADJUST_EXTRA_RSPACE (req );
611
+ (1U << - hp -> curr ))
559
612
return T_OK ;
560
- }
561
613
}
562
614
/*
563
615
* The first condition here equivalent to the
@@ -581,10 +633,8 @@ do { \
581
633
}
582
634
}
583
635
if (likely (offset == 0 )) {
584
- if ((i ^ (HT_EOS_HIGH >> 1 )) < (1U << - hp -> curr )) {
585
- ADJUST_EXTRA_RSPACE (req );
636
+ if ((i ^ (HT_EOS_HIGH >> 1 )) < (1U << - hp -> curr ))
586
637
return T_OK ;
587
- }
588
638
}
589
639
return T_COMPRESSION ;
590
640
0 commit comments