1*e7be843bSPierre ProncheryStream Receive Buffers 2*e7be843bSPierre Pronchery====================== 3*e7be843bSPierre Pronchery 4*e7be843bSPierre ProncheryThis is a QUIC specific module that retains the received stream data 5*e7be843bSPierre Proncheryuntil the application reads it with SSL_read() or any future stream read 6*e7be843bSPierre Proncherycalls. 7*e7be843bSPierre Pronchery 8*e7be843bSPierre ProncheryReceive Buffers requirements for MVP 9*e7be843bSPierre Pronchery------------------------------------ 10*e7be843bSPierre Pronchery 11*e7be843bSPierre ProncheryThese are the requirements that were identified for MVP: 12*e7be843bSPierre Pronchery 13*e7be843bSPierre Pronchery- As packets with stream frames are received in arbitrary frames the 14*e7be843bSPierre Pronchery received data must be stored until all the data with earlier offsets 15*e7be843bSPierre Pronchery are received. 16*e7be843bSPierre Pronchery- As packets can be received before application calls SSL_read() to read 17*e7be843bSPierre Pronchery the data the data must be stored. 18*e7be843bSPierre Pronchery- The application should be able to set the limit on how much data should 19*e7be843bSPierre Pronchery be stored. The flow controller should be used to limit the peer to not send 20*e7be843bSPierre Pronchery more data. Without the flow control limit a rogue peer could trigger 21*e7be843bSPierre Pronchery a DoS via unlimited flow of incoming stream data frames. 22*e7be843bSPierre Pronchery- After the data is passed via SSL_read() to the application the stored 23*e7be843bSPierre Pronchery data can be released and flow control limit can be raised. 24*e7be843bSPierre Pronchery- As the peer can recreate stream data frames when resending them, the 25*e7be843bSPierre Pronchery implementation must be able to handle properly frames with partially 26*e7be843bSPierre Pronchery or fully overlapping data with previously received frames. 27*e7be843bSPierre Pronchery 28*e7be843bSPierre ProncheryOptional Receive Buffers requirements 29*e7be843bSPierre Pronchery------------------------------------- 30*e7be843bSPierre Pronchery 31*e7be843bSPierre ProncheryThese are optional features of the stream receive buffers implementation. 32*e7be843bSPierre ProncheryThey are not required for MVP but they are otherwise desirable: 33*e7be843bSPierre Pronchery 34*e7be843bSPierre Pronchery- To support a single copy operation with a future stream read call 35*e7be843bSPierre Pronchery the received data should not be copied out of the decrypted packets to 36*e7be843bSPierre Pronchery store the data. The only information actually stored would be a list 37*e7be843bSPierre Pronchery of offset, length, and pointers to data, along with a pointer to the 38*e7be843bSPierre Pronchery decrypted QUIC packet that stores the actual frame. 39*e7be843bSPierre Pronchery 40*e7be843bSPierre ProncheryProposed new public API calls 41*e7be843bSPierre Pronchery----------------------------- 42*e7be843bSPierre Pronchery 43*e7be843bSPierre Pronchery```C 44*e7be843bSPierre Proncheryint SSL_set_max_stored_stream_data(SSL *stream, size_t length); 45*e7be843bSPierre Pronchery``` 46*e7be843bSPierre Pronchery 47*e7be843bSPierre ProncheryThis function adjusts the current data flow control limit on the `stream` 48*e7be843bSPierre Proncheryto allow storing `length` bytes of quic stream data before it is read by 49*e7be843bSPierre Proncherythe application. 50*e7be843bSPierre Pronchery 51*e7be843bSPierre ProncheryOpenSSL handles sending MAX_STREAM_DATA frames appropriately when the 52*e7be843bSPierre Proncheryapplication reads the stored data. 53*e7be843bSPierre Pronchery 54*e7be843bSPierre Pronchery```C 55*e7be843bSPierre Proncheryint SSL_set_max_unprocessed_packet_data(SSL *connection, 56*e7be843bSPierre Pronchery size_t length); 57*e7be843bSPierre Pronchery``` 58*e7be843bSPierre Pronchery 59*e7be843bSPierre ProncheryThis sets the limit on unprocessed quic packet data `length` in bytes that 60*e7be843bSPierre Proncheryis allowed to be allocated for the `connection`. 61*e7be843bSPierre ProncherySee the [Other considerations](#other-considerations) section below. 62*e7be843bSPierre Pronchery 63*e7be843bSPierre ProncheryInterfaces to other QUIC implementation modules 64*e7be843bSPierre Pronchery----------------------------------------------- 65*e7be843bSPierre Pronchery 66*e7be843bSPierre Pronchery### Front End I/O API 67*e7be843bSPierre Pronchery 68*e7be843bSPierre ProncherySSL_read() copies data out of the stored buffers if available and 69*e7be843bSPierre Proncheryeventually triggers release of stored unprocessed packet(s). 70*e7be843bSPierre Pronchery 71*e7be843bSPierre ProncherySSL_peek(), SSL_pending(), SSL_has_pending() peek into the stored 72*e7be843bSPierre Proncherybuffers for any information about the stored data. 73*e7be843bSPierre Pronchery 74*e7be843bSPierre Pronchery### RX Depacketizer 75*e7be843bSPierre Pronchery 76*e7be843bSPierre ProncheryThe Receive Buffers module obtains the stream data via the ssl_queue_data() 77*e7be843bSPierre Proncherycallback. 78*e7be843bSPierre Pronchery 79*e7be843bSPierre ProncheryThe module uses ossl_qrx_pkt_wrap_up_ref() and ossl_qrx_pkt_wrap_release() 80*e7be843bSPierre Proncheryfunctions to keep and release decrypted packets with unprocessed data. 81*e7be843bSPierre Pronchery 82*e7be843bSPierre Pronchery### Flow Control 83*e7be843bSPierre Pronchery 84*e7be843bSPierre ProncheryThe Receive Buffers module provides an appropriate value for the Flow 85*e7be843bSPierre ProncheryControl module to send MAX_DATA and MAX_STREAM_DATA frames. Details 86*e7be843bSPierre ProncheryTBD. 87*e7be843bSPierre Pronchery 88*e7be843bSPierre Pronchery### QUIC Read Record Layer 89*e7be843bSPierre Pronchery 90*e7be843bSPierre ProncheryThe Receive Buffers module needs to know whether it should stop holding 91*e7be843bSPierre Proncherythe decrypted quic packets and start copying the stream data due to 92*e7be843bSPierre Proncherythe limit reached. See the `SSL_set_max_unprocessed_quic_packet_data()` 93*e7be843bSPierre Proncheryfunction above and the [Other considerations](#other-considerations) section 94*e7be843bSPierre Proncherybelow. Details TBD. 95*e7be843bSPierre Pronchery 96*e7be843bSPierre ProncheryImplementation details 97*e7be843bSPierre Pronchery---------------------- 98*e7be843bSPierre Pronchery 99*e7be843bSPierre ProncheryThe QUIC_RSTREAM object holds the received stream data in the SFRAME_LIST 100*e7be843bSPierre Proncherystructure. This is a sorted list of partially (never fully) overlapping 101*e7be843bSPierre Proncherydata frames. Each list item holds a pointer to the received packet 102*e7be843bSPierre Proncherywrapper for refcounting and proper release of the received packet 103*e7be843bSPierre Proncherydata once the stream data is read by the application. 104*e7be843bSPierre Pronchery 105*e7be843bSPierre ProncheryEach SFRAME_LIST item has range.start and range.end values greater 106*e7be843bSPierre Proncherythan the range.start and range.end values of the previous item in the list. 107*e7be843bSPierre ProncheryThis invariant is ensured on the insertion of overlapping stream frames. 108*e7be843bSPierre ProncheryAny redundant frames are released. Insertion at the end of the list 109*e7be843bSPierre Proncheryis optimised as in the ideal situation when no packets are lost we 110*e7be843bSPierre Proncheryalways just append new frames. 111*e7be843bSPierre Pronchery 112*e7be843bSPierre ProncherySee `include/internal/quic_stream.h` and `include/internal/quic_sf_list.h` 113*e7be843bSPierre Proncheryfor internal API details. 114*e7be843bSPierre Pronchery 115*e7be843bSPierre ProncheryOther considerations 116*e7be843bSPierre Pronchery-------------------- 117*e7be843bSPierre Pronchery 118*e7be843bSPierre ProncheryThe peer is allowed to recreate the stream data frames. As we aim for 119*e7be843bSPierre Proncherya single-copy operation a rogue peer could use this to override the stored 120*e7be843bSPierre Proncherydata limits by sending duplicate frames with only slight changes in the 121*e7be843bSPierre Proncheryoffset. For example: 1st frame - offset 0 length 1000, 2nd frame - 122*e7be843bSPierre Proncheryoffset 1 length 1000, 3rd frame - offset 2 length 1000, and so on. We 123*e7be843bSPierre Proncherywould have to keep the packet data for all these frames which would 124*e7be843bSPierre Proncheryeffectively raise the stream data flow control limit quadratically. 125*e7be843bSPierre Pronchery 126*e7be843bSPierre ProncheryAnd this is not the only way how a rogue peer could make us occupy much 127*e7be843bSPierre Proncherymore data than what is allowed by the stream data flow control limit 128*e7be843bSPierre Proncheryin the single-copy scenario. 129*e7be843bSPierre Pronchery 130*e7be843bSPierre ProncheryAlthough intuitively the MAX_DATA flow control limit might be used to 131*e7be843bSPierre Proncherysomehow limit the allocated packet buffer size, it is defined as sum 132*e7be843bSPierre Proncheryof allowed data to be sent across all the streams in the connection instead. 133*e7be843bSPierre ProncheryThe packet buffer will contain much more data than just the stream frames 134*e7be843bSPierre Proncheryespecially with a rogue peer, that means MAX_DATA limit cannot be used 135*e7be843bSPierre Proncheryto limit the memory occupied by packet buffers. 136*e7be843bSPierre Pronchery 137*e7be843bSPierre ProncheryTo resolve this problem, we fall back to copying the data off the 138*e7be843bSPierre Proncherydecrypted packet buffer once we reach a limit on unprocessed decrypted 139*e7be843bSPierre Proncherypackets. We might also consider falling back to copying the data in case 140*e7be843bSPierre Proncherywe receive stream data frames that are partially overlapping and one frame 141*e7be843bSPierre Proncherynot being a subrange of the other. 142*e7be843bSPierre Pronchery 143*e7be843bSPierre ProncheryBecause in MVP only a single bidirectional stream to receive 144*e7be843bSPierre Proncheryany data will be supported, the MAX_DATA flow control limit should be equal 145*e7be843bSPierre Proncheryto MAX_STREAM_DATA limit for that stream. 146