Skip to content

Commit be82e49

Browse files
handle anonymous frames correctly
1 parent bc2dc12 commit be82e49

File tree

1 file changed

+46
-29
lines changed

1 file changed

+46
-29
lines changed

libcanard/canard.c

Lines changed: 46 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -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

13541359
static 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

Comments
 (0)