@@ -169,9 +169,11 @@ bool udpard_is_valid_endpoint(const udpard_udpip_ep_t ep)
169169static uint16_t valid_ep_bitmap (const udpard_udpip_ep_t remote_ep [UDPARD_IFACE_COUNT_MAX ])
170170{
171171 uint16_t bitmap = 0U ;
172- for (size_t i = 0 ; i < UDPARD_IFACE_COUNT_MAX ; i ++ ) {
173- if (udpard_is_valid_endpoint (remote_ep [i ])) {
174- bitmap |= (1U << i );
172+ if (remote_ep != NULL ) {
173+ for (size_t i = 0 ; i < UDPARD_IFACE_COUNT_MAX ; i ++ ) {
174+ if (udpard_is_valid_endpoint (remote_ep [i ])) {
175+ bitmap |= (1U << i );
176+ }
175177 }
176178 }
177179 return bitmap ;
@@ -1323,6 +1325,46 @@ void udpard_tx_poll(udpard_tx_t* const self, const udpard_us_t now, const uint16
13231325 }
13241326}
13251327
1328+ size_t udpard_tx_redirect (udpard_tx_t * const self ,
1329+ const uint64_t topic_hash ,
1330+ const udpard_udpip_ep_t remote_ep [UDPARD_IFACE_COUNT_MAX ])
1331+ {
1332+ size_t out = 0 ;
1333+ if ((self != NULL ) && (valid_ep_bitmap (remote_ep ) != 0 )) {
1334+ // Transfers are ordered lexicographically by (topic_hash, transfer_id), so we can find the first one
1335+ // with a lower_bound search and then iterate until the topic_hash changes.
1336+ const tx_transfer_key_t key = { .topic_hash = topic_hash , .transfer_id = 0 };
1337+ tx_transfer_t * tr = CAVL2_TO_OWNER (
1338+ cavl2_lower_bound (self -> index_transfer , & key , & tx_cavl_compare_transfer ), tx_transfer_t , index_transfer );
1339+ UDPARD_ASSERT ((tr == NULL ) || (tr -> topic_hash >= topic_hash ));
1340+ while ((tr != NULL ) && (tr -> topic_hash == topic_hash )) {
1341+ for (size_t i = 0 ; i < UDPARD_IFACE_COUNT_MAX ; i ++ ) {
1342+ // We don't want to enable transmission over a new interface that was not originally intended for
1343+ // this transfer. This matters with time synchronization messages, for example.
1344+ if (udpard_is_valid_endpoint (tr -> destination [i ]) && udpard_is_valid_endpoint (remote_ep [i ])) {
1345+ tr -> destination [i ] = remote_ep [i ];
1346+ }
1347+ }
1348+ out ++ ;
1349+ tr = CAVL2_TO_OWNER (cavl2_next_greater (& tr -> index_transfer ), tx_transfer_t , index_transfer );
1350+ }
1351+ }
1352+ return out ;
1353+ }
1354+
1355+ bool udpard_tx_cancel (udpard_tx_t * const self , const uint64_t topic_hash , const uint64_t transfer_id )
1356+ {
1357+ bool cancelled = false;
1358+ if (self != NULL ) {
1359+ tx_transfer_t * const tr = tx_transfer_find (self , topic_hash , transfer_id );
1360+ if (tr != NULL ) {
1361+ tx_transfer_retire (self , tr , false);
1362+ cancelled = true;
1363+ }
1364+ }
1365+ return cancelled ;
1366+ }
1367+
13261368uint16_t udpard_tx_pending_ifaces (const udpard_tx_t * const self )
13271369{
13281370 uint16_t bitmap = 0 ;
@@ -1365,19 +1407,6 @@ void udpard_tx_refcount_dec(const udpard_bytes_t tx_payload_view)
13651407 }
13661408}
13671409
1368- bool udpard_tx_cancel (udpard_tx_t * const self , const uint64_t topic_hash , const uint64_t transfer_id )
1369- {
1370- bool cancelled = false;
1371- if (self != NULL ) {
1372- tx_transfer_t * const tr = tx_transfer_find (self , topic_hash , transfer_id );
1373- if (tr != NULL ) {
1374- tx_transfer_retire (self , tr , false);
1375- cancelled = true;
1376- }
1377- }
1378- return cancelled ;
1379- }
1380-
13811410void udpard_tx_free (udpard_tx_t * const self )
13821411{
13831412 if (self != NULL ) {
0 commit comments