@@ -58,10 +58,15 @@ typedef unsigned char byte_t; ///< For compatibility with platforms where byte s
5858
5959/// The number of most recent transfers to keep in the history for ACK retransmission and duplicate detection.
6060/// Should be a power of two to allow replacement of modulo operation with a bitwise AND.
61+ ///
62+ /// Implementation node: we used to store bitmask windows instead of a full list of recent transfer-IDs, but they
63+ /// were found to offer no advantage except in the perfect scenario of non-restarting senders, and an increased
64+ /// implementation complexity (more branches, more lines of code), so they were replaced with a simple list.
65+ /// The list works equally well given a non-contiguous transfer-ID stream, unlike the bitmask, thus more robust.
6166#define RX_TRANSFER_HISTORY_COUNT 16U
6267
6368/// In the ORDERED reassembly mode, with the most recently received transfer-ID N, the library will reject
64- /// transfers with transfer-ID less than or equal to N - ORDERING_WINDOW (modulo 2^64) as late.
69+ /// transfers with transfer-ID less than or equal to N- ORDERING_WINDOW (modulo 2^64) as late.
6570#define RX_TRANSFER_ORDERING_WINDOW 1024U
6671
6772#define UDP_PORT 9382U
@@ -1310,7 +1315,6 @@ static void rx_session_ordered_scan_slots(rx_session_t* const self,
13101315 UDPARD_ASSERT ((slot != NULL ) && (slot -> state == rx_slot_done ));
13111316 rx_session_eject (self , rx , slot );
13121317 }
1313-
13141318 // Ensure that in-progress slots, if any, have not ended up within the accepted window after the update.
13151319 // We can release them early to avoid holding the payload buffers that won't be used anyway.
13161320 for (size_t i = 0 ; i < RX_SLOT_COUNT ; i ++ ) {
@@ -1387,6 +1391,7 @@ static void rx_session_update_ordered(rx_session_t* const self,
13871391 const rx_frame_t frame ,
13881392 const udpard_mem_deleter_t payload_deleter )
13891393{
1394+ // The queries here may be a bit time-consuming. If this becomes a problem, there are many ways to optimize this.
13901395 const bool is_ejected = rx_session_is_transfer_ejected (self , frame .meta .transfer_id );
13911396 const bool is_late_or_ejected = rx_session_is_transfer_late_or_ejected (self , frame .meta .transfer_id );
13921397 const bool is_interned = rx_session_is_transfer_interned (self , frame .meta .transfer_id );
@@ -1413,6 +1418,9 @@ static void rx_session_update_ordered(rx_session_t* const self,
14131418 rx_session_ordered_scan_slots (self , rx , ts , false);
14141419 }
14151420 } else { // retransmit ACK if needed
1421+ // Note: transfers that are no longer retained in the history will not solicit an ACK response,
1422+ // meaning that the sender will not get a confirmation if the retransmitted transfer is too old.
1423+ // We assume that RX_TRANSFER_HISTORY_COUNT is enough to cover all sensible use cases.
14161424 if ((is_interned || is_ejected ) && frame .meta .flag_ack && (frame .base .offset == 0U )) {
14171425 rx_session_on_ack_mandate (self , rx , frame .meta .priority , frame .meta .transfer_id , frame .base .payload );
14181426 }
0 commit comments