@@ -1320,40 +1320,45 @@ static size_t rx_session_cleanup(rx_session_t* const ses, const canard_us_t now)
13201320 return n_slots ;
13211321}
13221322
1323- static void rx_session_complete (rx_session_t * const ses , const canard_us_t ts_frame , const frame_t * const fr )
1323+ static void rx_session_complete_single_frame (canard_subscription_t * const sub ,
1324+ const canard_us_t ts ,
1325+ const frame_t * const fr )
13241326{
1325- canard_subscription_t * const sub = ses -> owner ;
1326- CANARD_ASSERT ((fr -> end ) && (fr -> port_id == sub -> port_id ) && (fr -> kind == sub -> kind ));
1327+ CANARD_ASSERT (fr -> start && fr -> end && (fr -> port_id == sub -> port_id ) && (fr -> kind == sub -> kind ));
13271328 CANARD_ASSERT (sub -> vtable -> on_message != NULL );
1328- rx_slot_t * const slot = ses -> slots [fr -> priority ];
1329- if (slot == NULL ) {
1330- CANARD_ASSERT (fr -> start && fr -> end ); // Only single-frame can complete without a slot.
1331- const canard_payload_t payload = { .view = fr -> payload , .origin = { .data = NULL , .size = 0 } };
1332- sub -> vtable -> on_message (sub , ts_frame , fr -> priority , fr -> src , fr -> transfer_id , payload );
1329+ const canard_payload_t payload = { .view = fr -> payload , .origin = { .data = NULL , .size = 0 } };
1330+ sub -> vtable -> on_message (sub , ts , fr -> priority , fr -> src , fr -> transfer_id , payload );
1331+ }
1332+
1333+ static void rx_session_complete_slot (rx_session_t * const ses , const frame_t * const fr )
1334+ {
1335+ canard_subscription_t * const sub = ses -> owner ;
1336+ rx_slot_t * const slot = ses -> slots [fr -> priority ];
1337+ CANARD_ASSERT (!fr -> start && fr -> end && (fr -> port_id == sub -> port_id ) && (fr -> kind == sub -> kind ));
1338+ CANARD_ASSERT ((slot != NULL ) && (sub -> vtable -> on_message != NULL ));
1339+ CANARD_ASSERT ((slot -> transfer_id == fr -> transfer_id ) && (slot -> iface_index == ses -> iface_index ));
1340+ CANARD_ASSERT (fr -> src != CANARD_NODE_ID_ANONYMOUS ); // anons cannot be multiframe
1341+ // Verify the CRC and dispatch the message if correct. The slot is consumed in either case.
1342+ ses -> slots [fr -> priority ] = NULL ; // Slot memory ownership transferred to the application, or destroyed.
1343+ const bool v1 = canard_kind_version (sub -> kind ) == 1 ;
1344+ const uint16_t crc_ref = v1 ? CRC_RESIDUE : (uint16_t )(slot -> payload [0 ] | (((unsigned )slot -> payload [1 ]) << 8U ));
1345+ CANARD_ASSERT (v1 || (sub -> extent >= 2 )); // In v0, the CRC size is included in the extent.
1346+ if (slot -> crc == crc_ref ) {
1347+ const size_t size = smaller (slot -> total_size - 2 , sub -> extent - (v1 ? 0 : 2 ));
1348+ const canard_payload_t payload = {
1349+ .view = { .data = v1 ? slot -> payload : & slot -> payload [2 ], .size = size },
1350+ .origin = { .data = slot , .size = RX_SLOT_OVERHEAD + sub -> extent },
1351+ };
1352+ sub -> vtable -> on_message (sub , slot -> start_ts , fr -> priority , fr -> src , fr -> transfer_id , payload );
13331353 } else {
1334- CANARD_ASSERT (!fr -> start && fr -> end );
1335- CANARD_ASSERT ((slot -> transfer_id == fr -> transfer_id ) && (slot -> iface_index == ses -> iface_index ));
1336- ses -> slots [fr -> priority ] = NULL ; // Slot memory ownership transferred to the application, or destroyed.
1337- const bool v1 = canard_kind_version (sub -> kind ) == 1 ;
1338- const uint16_t crc_ref = v1 ? CRC_RESIDUE : (uint16_t )(slot -> payload [0 ] | (((unsigned )slot -> payload [1 ]) << 8U ));
1339- CANARD_ASSERT (v1 || (sub -> extent >= 2 )); // In v0, the CRC size is included in the extent.
1340- if (slot -> crc == crc_ref ) {
1341- const size_t size = smaller (slot -> total_size - 2 , sub -> extent - (v1 ? 0 : 2 ));
1342- const canard_payload_t payload = {
1343- .view = { .data = v1 ? slot -> payload : & slot -> payload [2 ], .size = size },
1344- .origin = { .data = slot , .size = RX_SLOT_OVERHEAD + sub -> extent },
1345- };
1346- sub -> vtable -> on_message (sub , slot -> start_ts , fr -> priority , fr -> src , fr -> transfer_id , payload );
1347- } else {
1348- sub -> owner -> err .rx_transfer ++ ;
1349- rx_slot_destroy (ses -> owner , slot );
1350- }
1354+ sub -> owner -> err .rx_transfer ++ ;
1355+ rx_slot_destroy (ses -> owner , slot );
13511356 }
13521357}
13531358
13541359static void rx_session_accept (rx_session_t * const ses , const canard_us_t ts_frame , const frame_t * const fr )
13551360{
1356- const canard_subscription_t * const sub = ses -> owner ;
1361+ canard_subscription_t * const sub = ses -> owner ;
13571362 CANARD_ASSERT ((fr -> port_id == sub -> port_id ) && (fr -> kind == sub -> kind ));
13581363 rx_slot_t * const slot = ses -> slots [fr -> priority ];
13591364 if (slot != NULL ) {
@@ -1370,9 +1375,12 @@ static void rx_session_accept(rx_session_t* const ses, const canard_us_t ts_fram
13701375 ? (canard_bytes_t ){ .size = fr -> payload .size - 2 , .data = ((byte_t * )fr -> payload .data ) + 2 }
13711376 : fr -> payload ;
13721377 slot -> crc = crc_add (slot -> crc , crc_input .size , crc_input .data );
1373- }
1374- if (fr -> end ) {
1375- rx_session_complete (ses , ts_frame , fr );
1378+ if (fr -> end ) {
1379+ rx_session_complete_slot (ses , fr );
1380+ }
1381+ } else {
1382+ CANARD_ASSERT (fr -> start && fr -> end );
1383+ rx_session_complete_single_frame (sub , ts_frame , fr );
13761384 }
13771385}
13781386
@@ -1463,6 +1471,15 @@ static void rx_session_update(canard_subscription_t* const sub,
14631471 CANARD_ASSERT ((frame -> dst == CANARD_NODE_ID_ANONYMOUS ) || (frame -> dst == sub -> owner -> node_id ));
14641472 CANARD_ASSERT ((canard_kind_version (sub -> kind ) != 0 ) || (sub -> extent >= 2 )); // v0 CRC reservation
14651473
1474+ // Anonymous frames are stateless and require special treatment.
1475+ // They are scheduled to be deprecated in Cyphal v1.1 and their support will be eventually dropped.
1476+ if (frame -> src == CANARD_NODE_ID_ANONYMOUS ) {
1477+ CANARD_ASSERT (frame -> start && frame -> end && (frame -> dst == CANARD_NODE_ID_ANONYMOUS ));
1478+ CANARD_ASSERT ((frame -> kind == canard_kind_0v1_message ) || (frame -> kind == canard_kind_1v0_message ));
1479+ rx_session_complete_single_frame (sub , ts , frame );
1480+ return ;
1481+ }
1482+
14661483 // Only start frames may create new states.
14671484 // The protocol version is observable on start frames by design, which makes this robust.
14681485 // At this point we also ensured the frame is not misaddressed.
0 commit comments