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 = 0; \
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 ); \
@@ -316,13 +355,12 @@ do { \
316
355
goto out ; \
317
356
} \
318
357
if (!TFW_STR_EMPTY (& it -> hdr )) { \
319
- r = tfw_hpack_exp_hdr(req->pool, len, \
320
- it); \
358
+ r = tfw_hpack_exp_hdr (req -> pool , 0 , it ); \
321
359
if (unlikely (r )) \
322
360
return r ; \
323
361
it -> next = it -> hdr .nchunks - 1 ; \
324
362
} else { \
325
- BUFFER_HDR_INIT(length, it); \
363
+ BUFFER_HDR_INIT (it ); \
326
364
} \
327
365
} \
328
366
} while (0 )
@@ -460,41 +498,61 @@ static inline int
460
498
tfw_hpack_huffman_write (char sym , TfwHttpReq * __restrict req )
461
499
{
462
500
TfwMsgParseIter * it = & req -> pit ;
501
+ unsigned long to_alloc ;
463
502
bool np ;
464
503
int r ;
465
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)
518
+
466
519
if (it -> rspace ) {
467
520
-- it -> rspace ;
468
521
* it -> pos ++ = sym ;
522
+ ADJUST_HDR_LEN (it );
469
523
return 0 ;
470
524
}
471
525
472
- if (!(it -> pos = tfw_pool_alloc_not_align_np (it -> pool , 1 , & np )))
473
- return - ENOMEM ;
526
+ to_alloc = it -> to_alloc ? it -> to_alloc : 1 ;
527
+ if (to_alloc > 1 )
528
+ it -> rspace = to_alloc - 1 ;
474
529
475
- * it -> pos = sym ;
530
+ it -> pos = tfw_pool_alloc_not_align_np (it -> pool , to_alloc , & np );
531
+ if (!it -> pos )
532
+ return - ENOMEM ;
476
533
477
534
T_DBG3 ("%s: it->rspace=%lu, sym=%c, np=%d\n" , __func__ ,
478
535
it -> rspace , sym , np );
479
536
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 ;
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 );
491
546
return 0 ;
492
547
}
493
548
494
549
r = tfw_hpack_exp_hdr (req -> pool , 1 , it );
495
550
if (unlikely (r ))
496
551
return r ;
497
552
553
+ * it -> pos ++ = sym ;
554
+ it -> to_alloc = 0 ;
555
+
498
556
return 0 ;
499
557
}
500
558
@@ -506,28 +564,14 @@ huffman_decode_tail(TfwHPack *__restrict hp, TfwHttpReq *__restrict req,
506
564
unsigned int i ;
507
565
int r ;
508
566
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
567
for (;;) {
522
568
int shift ;
523
569
524
570
if (hp -> curr == - HT_NBITS ) {
525
- if (likely (offset == 0 )) {
526
- ADJUST_EXTRA_RSPACE (req );
571
+ if (likely (offset == 0 ))
527
572
return T_OK ;
528
- } else {
573
+ else
529
574
return T_COMPRESSION ;
530
- }
531
575
}
532
576
533
577
i = (hp -> hctx << - hp -> curr ) & HT_NMASK ;
@@ -554,10 +598,8 @@ do { \
554
598
*/
555
599
if (likely (offset == 0 )) {
556
600
if ((i ^ (HT_EOS_HIGH >> 1 )) <
557
- (1U << - hp -> curr )) {
558
- ADJUST_EXTRA_RSPACE (req );
601
+ (1U << - hp -> curr ))
559
602
return T_OK ;
560
- }
561
603
}
562
604
/*
563
605
* The first condition here equivalent to the
@@ -581,10 +623,8 @@ do { \
581
623
}
582
624
}
583
625
if (likely (offset == 0 )) {
584
- if ((i ^ (HT_EOS_HIGH >> 1 )) < (1U << - hp -> curr )) {
585
- ADJUST_EXTRA_RSPACE (req );
626
+ if ((i ^ (HT_EOS_HIGH >> 1 )) < (1U << - hp -> curr ))
586
627
return T_OK ;
587
- }
588
628
}
589
629
return T_COMPRESSION ;
590
630
0 commit comments