@@ -134,83 +134,108 @@ void qc_stream_desc_release(struct qc_stream_desc *stream,
134134 }
135135}
136136
137+ /* Acknowledged data for buffer <buf> attached to <stream> instance. The
138+ * acknowledged STREAM starts at <offset> and is of length <len> with <fin>
139+ * sets for the last frame of the stream.
140+ *
141+ * Returns <buf> if there is still data to acknowledged after completing the
142+ * operation. Else, the next buffer instance of stream is returned if it exists
143+ * or NULL in the latter case.
144+ */
145+ static struct qc_stream_buf * qc_stream_buf_ack (struct qc_stream_buf * buf ,
146+ struct qc_stream_desc * stream ,
147+ uint64_t offset , uint64_t len , int fin )
148+ {
149+ if (offset + len > stream -> ack_offset ) {
150+ const uint64_t diff = offset + len - stream -> ack_offset ;
151+ b_del (& buf -> buf , diff );
152+ stream -> ack_offset += diff ;
153+ }
154+
155+ if (!b_data (& buf -> buf ) && eb_is_empty (& buf -> acked_frms )) {
156+ qc_stream_buf_free (stream , & buf );
157+ buf = NULL ;
158+ }
159+
160+ if (fin ) {
161+ /* Mark FIN as acknowledged. */
162+ stream -> flags &= ~QC_SD_FL_WAIT_FOR_FIN ;
163+ }
164+
165+ if (!buf && !eb_is_empty (& stream -> buf_tree ))
166+ buf = eb64_entry (eb64_first (& stream -> buf_tree ), struct qc_stream_buf , offset_node );
167+ return buf ;
168+ }
169+
137170/* Acknowledge <frm> STREAM frame whose content is managed by <stream>
138171 * descriptor.
139172 *
140173 * Returns 0 if the frame has been handled and can be removed.
141- * Returns a positive value if the frame cannot be acknowledged and has been
142- * buffered.
174+ * Returns a positive value if acknowledgement is out-of-order and
175+ * corresponding STREAM frame has been buffered.
143176 */
144177int qc_stream_desc_ack (struct qc_stream_desc * stream , struct quic_frame * frm )
145178{
146179 struct qf_stream * strm_frm = & frm -> stream ;
147- uint64_t offset = strm_frm -> offset .key ;
148- uint64_t len = strm_frm -> len ;
180+ size_t offset = strm_frm -> offset .key ;
181+ size_t len = strm_frm -> len ;
149182 int fin = frm -> type & QUIC_STREAM_FRAME_TYPE_FIN_BIT ;
150-
151183 struct qc_stream_buf * stream_buf = NULL ;
152184 struct eb64_node * buf_node ;
153- struct buffer * buf = NULL ;
154- size_t diff ;
185+ struct eb64_node * frm_node ;
186+ int ret = 0 ;
155187
156188 /* Cannot advertise FIN for an inferior data range. */
157189 BUG_ON (fin && offset + len < stream -> ack_offset );
158190
159- if (offset + len < stream -> ack_offset ) {
160- return 0 ;
191+ if (!len ) {
192+ BUG_ON (!fin ); /* An empty STREAM frame can only be used to advertise FIN */
193+ /* An empty FIN STREAM cannot be inferior to last ack offset. */
194+ BUG_ON (offset < stream -> ack_offset );
195+
196+ /* Empty STREAM frame with FIN can be acknowledged immediately. */
197+ stream -> flags &= ~QC_SD_FL_WAIT_FOR_FIN ;
161198 }
162199 else if (offset > stream -> ack_offset ) {
163200 buf_node = eb64_lookup_le (& stream -> buf_tree , offset );
164- if (buf_node ) {
165- stream_buf = eb64_entry (buf_node , struct qc_stream_buf , offset_node );
166- eb64_insert (& stream_buf -> acked_frms , & strm_frm -> offset );
167- return 1 ;
168- }
169- else {
170- ABORT_NOW ();
171- return 0 ;
172- }
201+ BUG_ON (!buf_node ); /* Cannot acknowledged a STREAM frame for a non existing buffer. */
202+ stream_buf = eb64_entry (buf_node , struct qc_stream_buf , offset_node );
203+ eb64_insert (& stream_buf -> acked_frms , & strm_frm -> offset );
204+ ret = 1 ;
173205 }
174-
175- diff = offset + len - stream -> ack_offset ;
176- if (diff ) {
206+ else if (offset + len > stream -> ack_offset ) {
177207 /* Buf list cannot be empty if there is still unacked data. */
178208 BUG_ON (eb_is_empty (& stream -> buf_tree ));
179209
180210 /* get oldest buffer from buf tree */
181211 stream_buf = eb64_entry (eb64_first (& stream -> buf_tree ), struct qc_stream_buf , offset_node );
182- buf = & stream_buf -> buf ;
212+ stream_buf = qc_stream_buf_ack ( stream_buf , stream , offset , len , fin ) ;
183213
184- stream -> ack_offset += diff ;
185- b_del (buf , diff );
186-
187- /* Free oldest buffer if all data acknowledged. */
188- if (!b_data (buf )) {
189- /* Remove buffered ACK before deleting buffer instance. */
190- while (!eb_is_empty (& stream_buf -> acked_frms )) {
191- struct quic_conn * qc = stream -> qc ;
192- struct eb64_node * frm_node ;
193- struct qf_stream * strm_frm ;
194- struct quic_frame * frm ;
195-
196- frm_node = eb64_first (& stream_buf -> acked_frms );
197- eb64_delete (frm_node );
198-
199- strm_frm = eb64_entry (frm_node , struct qf_stream , offset );
200- frm = container_of (strm_frm , struct quic_frame , stream );
201- qc_release_frm (qc , frm );
202- }
203- qc_stream_buf_free (stream , & stream_buf );
204- buf = NULL ;
205- }
206- }
214+ /* some data were acknowledged, try to consume any remaining buffered ACK. */
215+ frm_node = stream_buf ? eb64_first (& stream_buf -> acked_frms ) : NULL ;
216+ while (frm_node ) {
217+ strm_frm = eb64_entry (frm_node , struct qf_stream , offset );
218+ frm = container_of (strm_frm , struct quic_frame , stream );
207219
208- if (fin ) {
209- /* Mark FIN as acknowledged. */
210- stream -> flags &= ~QC_SD_FL_WAIT_FOR_FIN ;
220+ offset = strm_frm -> offset .key ;
221+ len = strm_frm -> len ;
222+ fin = frm -> type & QUIC_STREAM_FRAME_TYPE_FIN_BIT ;
223+
224+ if (offset > stream -> ack_offset )
225+ break ;
226+
227+ /* Delete frame before acknowledged it. This prevents BUG_ON()
228+ * on non-empty acked_frms tree when stream_buf is empty and removed.
229+ */
230+ eb64_delete (frm_node );
231+ stream_buf = qc_stream_buf_ack (stream_buf , stream , offset , len , fin );
232+ qc_release_frm (NULL , frm );
233+
234+ frm_node = stream_buf ? eb64_first (& stream_buf -> acked_frms ) : NULL ;
235+ }
211236 }
212237
213- return 0 ;
238+ return ret ;
214239}
215240
216241/* Free the stream descriptor <stream> content. This function should be used
0 commit comments