@@ -223,7 +223,16 @@ qdh_out_on_write (struct lsquic_stream *stream, lsquic_stream_ctx_t *ctx)
223
223
LSQ_DEBUG ("wrote %zd bytes to stream" , nw );
224
224
(void ) lsquic_stream_flush (stream );
225
225
if (lsquic_frab_list_empty (& qdh -> qdh_fral ))
226
+ {
226
227
lsquic_stream_wantwrite (stream , 0 );
228
+ if (qdh -> qdh_on_dec_sent_func )
229
+ {
230
+ LSQ_DEBUG ("buffered data written: call callback" );
231
+ qdh -> qdh_on_dec_sent_func (qdh -> qdh_on_dec_sent_ctx );
232
+ qdh -> qdh_on_dec_sent_func = NULL ;
233
+ qdh -> qdh_on_dec_sent_ctx = NULL ;
234
+ }
235
+ }
227
236
}
228
237
else
229
238
{
@@ -294,7 +303,7 @@ qdh_read_encoder_stream (void *ctx, const unsigned char *buf, size_t sz,
294
303
s = lsqpack_dec_enc_in (& qdh -> qdh_decoder , buf , sz );
295
304
if (s != 0 )
296
305
{
297
- LSQ_INFO ("error reading decoder stream" );
306
+ LSQ_INFO ("error reading encoder stream" );
298
307
qerr = lsqpack_dec_get_err_info (& qdh -> qdh_decoder );
299
308
qdh -> qdh_conn -> cn_if -> ci_abort_error (qdh -> qdh_conn , 1 ,
300
309
HEC_QPACK_DECODER_STREAM_ERROR , "Error interpreting QPACK encoder "
@@ -376,6 +385,63 @@ qdh_hblock_unblocked (void *stream_p)
376
385
}
377
386
378
387
388
+ struct cont_len
389
+ {
390
+ unsigned long long value ;
391
+ int has ; /* 1: set, 0: not set, -1: invalid */
392
+ };
393
+
394
+
395
+ static void
396
+ process_content_length (const struct qpack_dec_hdl * qdh /* for logging */ ,
397
+ struct cont_len * cl , const char * val /* not NUL-terminated */ ,
398
+ unsigned len )
399
+ {
400
+ char * endcl , cont_len_buf [30 ];
401
+
402
+ if (0 == cl -> has )
403
+ {
404
+ if (len >= sizeof (cont_len_buf ))
405
+ {
406
+ LSQ_DEBUG ("content-length has invalid value `%.*s'" ,
407
+ (int ) len , val );
408
+ cl -> has = -1 ;
409
+ return ;
410
+ }
411
+ memcpy (cont_len_buf , val , len );
412
+ cont_len_buf [len ] = '\0' ;
413
+ cl -> value = strtoull (cont_len_buf , & endcl , 10 );
414
+ if (* endcl == '\0' && !(ULLONG_MAX == cl -> value && ERANGE == errno ))
415
+ {
416
+ cl -> has = 1 ;
417
+ LSQ_DEBUG ("content length is %llu" , cl -> value );
418
+ }
419
+ else
420
+ {
421
+ cl -> has = -1 ;
422
+ LSQ_DEBUG ("content-length has invalid value `%.*s'" ,
423
+ (int ) len , val );
424
+ }
425
+ }
426
+ else if (cl -> has > 0 )
427
+ {
428
+ LSQ_DEBUG ("header set has two content-length: ambiguous, "
429
+ "turn off checking" );
430
+ cl -> has = -1 ;
431
+ }
432
+ }
433
+
434
+
435
+ static int
436
+ is_content_length (const struct lsqpack_header * header )
437
+ {
438
+ return ((header -> qh_flags & QH_ID_SET ) && header -> qh_static_id == 4 )
439
+ || (header -> qh_name_len == 14 && header -> qh_name [0 ] == 'c'
440
+ && 0 == memcmp (header -> qh_name + 1 , "ontent-length" , 13 ))
441
+ ;
442
+ }
443
+
444
+
379
445
static int
380
446
qdh_supply_hset_to_stream (struct qpack_dec_hdl * qdh ,
381
447
struct lsquic_stream * stream , struct lsqpack_header_list * qlist )
@@ -387,6 +453,7 @@ qdh_supply_hset_to_stream (struct qpack_dec_hdl *qdh,
387
453
int push_promise ;
388
454
unsigned i ;
389
455
void * hset ;
456
+ struct cont_len cl ;
390
457
391
458
push_promise = lsquic_stream_header_is_pp (stream );
392
459
hset = hset_if -> hsi_create_header_set (qdh -> qdh_hsi_ctx , push_promise );
@@ -398,6 +465,7 @@ qdh_supply_hset_to_stream (struct qpack_dec_hdl *qdh,
398
465
399
466
LSQ_DEBUG ("got header set for stream %" PRIu64 , stream -> id );
400
467
468
+ cl .has = 0 ;
401
469
for (i = 0 ; i < qlist -> qhl_count ; ++ i )
402
470
{
403
471
header = qlist -> qhl_headers [i ];
@@ -412,6 +480,9 @@ qdh_supply_hset_to_stream (struct qpack_dec_hdl *qdh,
412
480
LSQ_INFO ("header process returned non-OK code %u" , (unsigned ) st );
413
481
goto err ;
414
482
}
483
+ if (is_content_length (header ))
484
+ process_content_length (qdh , & cl , header -> qh_value ,
485
+ header -> qh_value_len );
415
486
}
416
487
417
488
lsqpack_dec_destroy_header_list (qlist );
@@ -434,6 +505,8 @@ qdh_supply_hset_to_stream (struct qpack_dec_hdl *qdh,
434
505
goto err ;
435
506
LSQ_DEBUG ("converted qlist to hset and gave it to stream %" PRIu64 ,
436
507
stream -> id );
508
+ if (cl .has > 0 )
509
+ (void ) lsquic_stream_verify_len (stream , cl .value );
437
510
return 0 ;
438
511
439
512
err :
@@ -590,3 +663,24 @@ lsquic_qdh_cancel_stream (struct qpack_dec_hdl *qdh,
590
663
lsquic_qdh_unref_stream (qdh , stream );
591
664
}
592
665
}
666
+
667
+
668
+ int
669
+ lsquic_qdh_arm_if_unsent (struct qpack_dec_hdl * qdh , void (* func )(void * ),
670
+ void * ctx )
671
+ {
672
+ size_t bytes ;
673
+
674
+ /* Use size of a single frab list buffer as an arbitrary threshold */
675
+ bytes = lsquic_frab_list_size (& qdh -> qdh_fral );
676
+ if (bytes <= qdh -> qdh_fral .fl_buf_size )
677
+ return 0 ;
678
+ else
679
+ {
680
+ LSQ_DEBUG ("have %zu bytes of unsent QPACK decoder stream data: set "
681
+ "up callback" , bytes );
682
+ qdh -> qdh_on_dec_sent_func = func ;
683
+ qdh -> qdh_on_dec_sent_ctx = ctx ;
684
+ return 1 ;
685
+ }
686
+ }
0 commit comments