@@ -687,8 +687,7 @@ void udpard_tx_free(const udpard_tx_mem_resources_t memory, udpard_tx_item_t* co
687687typedef struct
688688{
689689 uint32_t index ;
690- uint32_t offset ; ///< Offset of this fragment's payload within the full transfer payload.
691- bool end_of_transfer ;
690+ uint32_t offset ; ///< Offset of this fragment's payload within the full transfer payload.
692691 udpard_bytes_t payload ; ///< Also contains the transfer CRC (but not the header CRC).
693692 udpard_bytes_mut_t origin ; ///< The entirety of the free-able buffer passed from the application.
694693} rx_frame_base_t ;
@@ -708,6 +707,66 @@ typedef struct rx_fragment_t
708707 udpard_tree_t tree ;
709708} rx_fragment_t ;
710709
710+ /// We require that the fragment tree does not contain fully-contained or equal-range fragments.
711+ /// One implication is that no two fragments can have the same offset.
712+ static int32_t rx_cavl_compare_fragment_offset (const void * const user , const udpard_tree_t * const node )
713+ {
714+ return ((* (const size_t * )user ) - CAVL2_TO_OWNER (node , rx_fragment_t , tree )-> base .offset ) ? +1 : -1 ;
715+ }
716+
717+ /// Find the first fragment where offset >= left in log time. Returns NULL if no such fragment exists.
718+ /// This is intended for overlap removal and gap detection when deciding if a new fragment is needed.
719+ static rx_fragment_t * rx_fragment_tree_lower_bound (udpard_tree_t * const root , const size_t left )
720+ {
721+ return CAVL2_TO_OWNER (cavl2_lower_bound (root , & left , & rx_cavl_compare_fragment_offset ), rx_fragment_t , tree );
722+ }
723+
724+ /// True if the fragment tree does not have a contiguous payload coverage in [left, right).
725+ /// This function requires that the tree does not have fully-contained fragments; one implication is that
726+ /// no two fragments may have the same offset.
727+ /// The complexity is O(log n + k), where n is the number of fragments in the tree and k is the number of fragments
728+ /// overlapping the specified range, assuming there are no fully-contained fragments.
729+ static bool rx_fragment_tree_has_gap_in_range (udpard_tree_t * const root , const size_t left , const size_t right )
730+ {
731+ if (left >= right ) {
732+ return false; // empty fragment; no gap by convention
733+ }
734+ rx_fragment_t * frag =
735+ CAVL2_TO_OWNER (cavl2_predecessor (root , & left , & rx_cavl_compare_fragment_offset ), rx_fragment_t , tree );
736+ if (frag == NULL ) {
737+ return true;
738+ }
739+ if ((frag -> base .offset + frag -> base .view .size ) <= left ) { // The predecessor ends before the left edge.
740+ return true;
741+ }
742+ size_t covered = left ; // This is the O(k) part. The scan starting point search is O(log n).
743+ while ((frag != NULL ) && (frag -> base .offset < right )) {
744+ if (frag -> base .offset > covered ) {
745+ return true;
746+ }
747+ covered = larger (covered , frag -> base .offset + frag -> base .view .size );
748+ if (covered >= right ) {
749+ return false; // Reached the end of the requested range without gaps.
750+ }
751+ frag = CAVL2_TO_OWNER (cavl2_next_greater (& frag -> tree ), rx_fragment_t , tree );
752+ }
753+ return covered < right ;
754+ }
755+
756+ /// True if the specified fragment should be retained. Otherwise, it is redundant and should be discarded.
757+ /// The complexity is O(log n + k), see rx_fragment_tree_has_gap_in_range() for details.
758+ static bool rx_fragment_is_needed (udpard_tree_t * const root ,
759+ const size_t fragment_offset ,
760+ const size_t fragment_size ,
761+ const size_t transfer_size ,
762+ const size_t extent )
763+ {
764+ const size_t total_size = smaller (transfer_size , extent );
765+ const size_t left = fragment_offset ;
766+ const size_t right = smaller (fragment_offset + fragment_size , total_size );
767+ return (left < total_size ) && rx_fragment_tree_has_gap_in_range (root , left , right );
768+ }
769+
711770typedef enum
712771{
713772 rx_slot_idle = 0 ,
@@ -804,7 +863,7 @@ typedef struct
804863 udpard_microsecond_t last_animated_ts ;
805864
806865 /// To weed out duplicates and to retransmit lost ACKs.
807- rx_transfer_id_window_t transfer_id_received ;
866+ rx_transfer_id_window_t acknowledged ;
808867
809868 rx_slot_t slots [RX_SLOT_COUNT ];
810869} rx_session_t ;
0 commit comments