@@ -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