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