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
+ * Save delta = len - it->rspace bytes. Later when
40
+ * `it->rspace` will be exceeded we use it to
41
+ * allocate new chunk;
42
+ */
43
+ #define BUFFER_GET (len , it ) \
44
+ do { \
45
+ BUG_ON(!(len)); \
46
+ if (!(it)->rspace) { \
47
+ (it)->rspace = len; \
48
+ (it)->pos = tfw_pool_alloc_not_align((it)->pool, len); \
49
+ T_DBG3("%s: get buffer, len=%lu, it->pos=[%p]," \
50
+ " it->pos=%lu\n", __func__, (unsigned long)len, \
51
+ (it)->pos, (unsigned long)(it)->pos); \
52
+ } else { \
53
+ (it)->to_alloc = len > (it)->rspace ? \
54
+ len - (it)->rspace : 0; \
55
+ } \
56
+ } while (0)
57
+
33
58
#define HP_HDR_NAME (name ) \
34
59
(&(TfwStr){ \
35
60
.chunks = &(TfwStr){ \
@@ -278,25 +303,32 @@ do { \
278
303
last - src); \
279
304
} while (0)
280
305
281
- #define BUFFER_HDR_INIT (length , it ) \
306
+ #define BUFFER_HDR_INIT (it ) \
282
307
do { \
283
308
(it)->hdr.data = (it)->pos; \
284
- (it)->hdr.len = length ; \
309
+ (it)->hdr.len = 0 ; \
285
310
(it)->next = &(it)->hdr; \
286
311
} while (0)
287
312
288
313
#define BUFFER_NAME_OPEN (length ) \
289
314
do { \
290
315
WARN_ON_ONCE(!TFW_STR_EMPTY(&it->hdr)); \
291
316
if (state & HPACK_FLAGS_HUFFMAN_NAME) { \
317
+ /* \
318
+ * Allocate extra 50% bytes. Huffman usually \
319
+ * gives compression benefit about 20 - 60 %. \
320
+ * Since we use extra allocated bytes for the \
321
+ * next header, we can allocate extra 50% bytes \
322
+ * without fear of losing a lot of memory. \
323
+ */ \
292
324
unsigned long len = length + (length >> 1 ); \
293
325
\
294
326
BUFFER_GET (len , it ); \
295
327
if (!it -> pos ) { \
296
328
r = - ENOMEM ; \
297
329
goto out ; \
298
330
} \
299
- BUFFER_HDR_INIT(len, it); \
331
+ BUFFER_HDR_INIT (it ); \
300
332
} \
301
333
} while (0 )
302
334
@@ -308,6 +340,13 @@ do { \
308
340
? it->parsed_hdr->nchunks \
309
341
: 1; \
310
342
if (state & HPACK_FLAGS_HUFFMAN_VALUE) { \
343
+ /* \
344
+ * Allocate extra 50% bytes. Huffman usually \
345
+ * gives compression benefit about 20 - 60 %. \
346
+ * Since we use extra allocated bytes for the \
347
+ * next header, we can allocate extra 50% bytes \
348
+ * without fear of losing a lot of memory. \
349
+ */ \
311
350
unsigned long len = length + (length >> 1 ); \
312
351
\
313
352
BUFFER_GET (len , it ); \
@@ -317,13 +356,13 @@ do { \
317
356
} \
318
357
if (!TFW_STR_EMPTY (& it -> hdr )) { \
319
358
it -> next = tfw_hpack_exp_hdr (req -> pool , \
320
- len , it); \
359
+ 0 , it ); \
321
360
if (!it -> next ) { \
322
361
r = - ENOMEM ; \
323
362
goto out ; \
324
363
} \
325
364
} else { \
326
- BUFFER_HDR_INIT(len, it); \
365
+ BUFFER_HDR_INIT (it ); \
327
366
} \
328
367
} \
329
368
} while (0 )
@@ -459,38 +498,61 @@ tfw_hpack_exp_hdr(TfwPool *__restrict pool, unsigned long len,
459
498
static inline int
460
499
tfw_hpack_huffman_write (char sym , TfwHttpReq * __restrict req )
461
500
{
462
- bool np ;
463
501
TfwMsgParseIter * it = & req -> pit ;
502
+ unsigned long to_alloc ;
503
+ bool np ;
504
+
505
+ #define ADJUST_HDR_LEN (it ) \
506
+ do { \
507
+ TfwStr *hdr = &it->hdr; \
508
+ TfwStr *last = TFW_STR_LAST(hdr); \
509
+ \
510
+ T_DBG3("%s: add to hdr, hdr->len=%lu, last->len=%lu," \
511
+ " last->data=%.*s\n", __func__, hdr->len, last->len, \
512
+ (int)last->len, last->data); \
513
+ \
514
+ ++hdr->len; \
515
+ if (!TFW_STR_PLAIN(hdr)) \
516
+ ++last->len; \
517
+ } while (0)
464
518
465
519
if (it -> rspace ) {
466
520
-- it -> rspace ;
467
521
* it -> pos ++ = sym ;
522
+ ADJUST_HDR_LEN (it );
468
523
return 0 ;
469
524
}
470
525
471
- if (!(it -> pos = tfw_pool_alloc_not_align_np (it -> pool , 1 , & np )))
472
- return - ENOMEM ;
526
+ to_alloc = it -> to_alloc ? it -> to_alloc : 1 ;
527
+ if (to_alloc > 1 )
528
+ it -> rspace = to_alloc - 1 ;
473
529
474
- * it -> pos = sym ;
530
+ it -> pos = tfw_pool_alloc_not_align_np (it -> pool , to_alloc , & np );
531
+ if (!it -> pos )
532
+ return - ENOMEM ;
475
533
476
534
T_DBG3 ("%s: it->rspace=%lu, sym=%c, np=%d\n" , __func__ ,
477
535
it -> rspace , sym , np );
478
536
479
- if (!np ) {
480
- TfwStr * hdr = & it -> hdr ;
481
- TfwStr * last = TFW_STR_LAST (hdr );
482
-
483
- T_DBG3 ("%s: add to hdr, hdr->len=%lu, last->len=%lu,"
484
- " last->data=%.*s\n" , __func__ , hdr -> len , last -> len ,
485
- (int )last -> len , last -> data );
486
-
487
- ++ hdr -> len ;
488
- if (!TFW_STR_PLAIN (hdr ))
489
- ++ last -> len ;
537
+ /*
538
+ * If the new page was allocated or it->pos points to
539
+ * the buffer, which was allocated to store previously
540
+ * decoded header (it->to_alloc != 0) we should expand
541
+ * header.
542
+ */
543
+ if (!np && !it -> to_alloc ) {
544
+ * it -> pos ++ = sym ;
545
+ ADJUST_HDR_LEN (it );
490
546
return 0 ;
491
547
}
492
548
493
- return tfw_hpack_exp_hdr (req -> pool , 1 , it ) ? 0 : - ENOMEM ;
549
+ if (!tfw_hpack_exp_hdr (req -> pool , 1 , it ))
550
+ return - ENOMEM ;
551
+
552
+ * it -> pos ++ = sym ;
553
+ it -> to_alloc = 0 ;
554
+
555
+ return 0 ;
494
556
}
495
557
496
558
static int
@@ -501,28 +563,14 @@ huffman_decode_tail(TfwHPack *__restrict hp, TfwHttpReq *__restrict req,
501
563
unsigned int i ;
502
564
int r ;
503
565
504
- #define ADJUST_EXTRA_RSPACE (req ) \
505
- do { \
506
- TfwMsgParseIter *it = &req->pit; \
507
- TfwStr *hdr = &it->hdr; \
508
- TfwStr *last = TFW_STR_LAST(hdr); \
509
- \
510
- hdr->len -= it->rspace; \
511
- if (!TFW_STR_PLAIN(hdr)) \
512
- last->len -= it->rspace; \
513
- it->rspace = 0; \
514
- } while (0)
515
-
516
566
for (;;) {
517
567
int shift ;
518
568
519
569
if (hp -> curr == - HT_NBITS ) {
520
- if (likely (offset == 0 )) {
521
- ADJUST_EXTRA_RSPACE (req );
570
+ if (likely (offset == 0 ))
522
571
return T_OK ;
523
- } else {
572
+ else
524
573
return T_COMPRESSION ;
525
- }
526
574
}
527
575
528
576
i = (hp -> hctx << - hp -> curr ) & HT_NMASK ;
@@ -549,10 +597,8 @@ do { \
549
597
*/
550
598
if (likely (offset == 0 )) {
551
599
if ((i ^ (HT_EOS_HIGH >> 1 )) <
552
- (1U << - hp -> curr )) {
553
- ADJUST_EXTRA_RSPACE (req );
600
+ (1U << - hp -> curr ))
554
601
return T_OK ;
555
- }
556
602
}
557
603
/*
558
604
* The first condition here equivalent to the
@@ -576,10 +622,8 @@ do { \
576
622
}
577
623
}
578
624
if (likely (offset == 0 )) {
579
- if ((i ^ (HT_EOS_HIGH >> 1 )) < (1U << - hp -> curr )) {
580
- ADJUST_EXTRA_RSPACE (req );
625
+ if ((i ^ (HT_EOS_HIGH >> 1 )) < (1U << - hp -> curr ))
581
626
return T_OK ;
582
- }
583
627
}
584
628
return T_COMPRESSION ;
585
629
0 commit comments