@@ -617,6 +617,17 @@ static byte_t txfer_shard(const canard_txfer_t* const tr)
617617
618618static bool txfer_is_backlogged (const canard_txfer_t * const tr ) { return tr -> delayed_until == HEAT_DEATH ; }
619619
620+ static bool txfer_is_pending (const canard_t * const self , const canard_txfer_t * const tr )
621+ {
622+ const byte_t shard = txfer_shard (tr );
623+ FOREACH_IFACE (i ) {
624+ if (is_listed (& self -> tx .pending [shard ][i ], & tr -> list_pending [i ])) {
625+ return true;
626+ }
627+ }
628+ return false;
629+ }
630+
620631static void txfer_free_payload (canard_t * const self , canard_txfer_t * const tr )
621632{
622633 CANARD_ASSERT (tr != NULL );
@@ -1006,9 +1017,10 @@ static bool tx_push(canard_t* const self,
10061017 // trying to push too many reliable transfers on the same topic too quickly.
10071018 // Insert at the same time to avoid double tree walk.
10081019 if (tr -> reliable ) {
1009- const txfer_key_t key = { .topic_hash = tr -> topic_hash , .transfer_id = tr -> transfer_id };
1010- canard_txfer_t * const rel = CAVL2_TO_OWNER (
1011- cavl2_find_or_insert (& self -> tx .reliable , & key , tx_cavl_compare_reliable , tr , cavl2_trivial_factory ),
1020+ const txfer_key_t key = { .topic_hash = tr -> topic_hash , .transfer_id = tr -> transfer_id };
1021+ const canard_txfer_t * const rel = CAVL2_TO_OWNER (
1022+ cavl2_find_or_insert (
1023+ & self -> tx .reliable , & key , tx_cavl_compare_reliable , & tr -> index_reliable , cavl2_trivial_factory ),
10121024 canard_txfer_t ,
10131025 index_reliable );
10141026 if (rel != tr ) { // Duplicate found.
@@ -1092,9 +1104,11 @@ static bool tx_push(canard_t* const self,
10921104 cavl2_lower_bound (self -> tx .reliable , & key , tx_cavl_compare_reliable ), canard_txfer_t , index_reliable );
10931105 while ((rel != NULL ) && (rel -> topic_hash == tr -> topic_hash )) {
10941106 if ((rel != tr ) && (txfer_shard (rel ) == shard )) {
1095- const bool delayed = rel -> delayed_until > BIG_BANG ; // Maybe backlogged also, but it's all the same.
1107+ // Check if the transfer is delayed (waiting for retransmission) or pending (waiting for first tx).
1108+ const bool delayed = rel -> delayed_until > BIG_BANG ; // In delayed list, waiting for retransmission.
1109+ const bool pending = txfer_is_pending (self , rel );
10961110 CANARD_ASSERT ((!delayed ) || is_listed (& self -> tx .delayed [shard ], & rel -> list_delayed ));
1097- if (delayed ) {
1111+ if (delayed || pending ) {
10981112 has_preceding_reliable = true;
10991113 break ;
11001114 }
@@ -1114,7 +1128,11 @@ static bool tx_push(canard_t* const self,
11141128 self -> tx .pending_shards_bitmap [i ] |= (1U << shard );
11151129 }
11161130 }
1117- tx_arm_delay_if (self , tr ); // Ensure it is repeatedly re-enqueued later until acknowledged or expired.
1131+ // tx_arm_delay_if is NOT called here; the retransmission timer is armed after transmission, not before.
1132+ // The transfer remains with delayed_until = BIG_BANG (set by txfer_new), ready for immediate transmission.
1133+ // For unreliable transfers, no retransmission is scheduled. For reliable transfers, the retransmission will be
1134+ // scheduled after the first transmission attempt completes.
1135+ CANARD_ASSERT (tr -> delayed_until == BIG_BANG );
11181136 }
11191137 return true;
11201138}
0 commit comments