cfdp: report a metadata only transaction as a complete delivery

A metadata only transaction - a proxy put request, for instance - carries no
file data and completes the moment its metadata arrives. handleTransferCompletion
took the branch for a null checksum, which sets the condition code and touches
neither delivery field, so both were reported at their reset defaults: a
transaction that succeeded announced itself as

  Finish Condition: No Error (0)
  File delivery code: Data Incomplete (1)
  File delivery status: Discard deliberately (0)

which contradicts itself, and goes out in the Finished PDU to the sender, not
only into the OBSW log. It was noticed on the flatsat, where every CFDP
downlink begins with exactly this kind of transaction carrying the proxy put
request, and each one reported a failed delivery on the console.

Nothing was expected of it and nothing is missing, so the delivery code is
DATA_COMPLETE; there is no file whose status could be reported, so the status
is FILE_STATUS_UNREPORTED.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N4eBFnanCACYWdKCzhHMcC
This commit is contained in:
Tobias Baumgartl
2026-09-16 16:40:12 +02:00
co-authored by Claude Opus 5
parent 844faf850f
commit 6faea2b0f0
2 changed files with 39 additions and 0 deletions
+9
View File
@@ -502,6 +502,15 @@ ReturnValue_t cfdp::DestHandler::handleTransferCompletion() {
}
} else {
transactionParams.conditionCode = ConditionCode::NO_ERROR;
if (transactionParams.metadataOnly) {
// Nothing was expected, so nothing is missing: a metadata only transaction - a proxy put
// request, say - carries no file data and completes the moment its metadata arrives. Both
// fields are otherwise left at the reset defaults, which report a successful transaction as
// "Data Incomplete" and "Discard deliberately". That contradicts the NO_ERROR condition code
// beside it, and it goes out in the Finished PDU, not just into the log.
transactionParams.deliveryCode = FileDeliveryCode::DATA_COMPLETE;
transactionParams.deliveryStatus = FileDeliveryStatus::FILE_STATUS_UNREPORTED;
}
}
result = noticeOfCompletion();
if (result != OK) {
@@ -132,6 +132,36 @@ TEST_CASE("CFDP Dest Handler", "[cfdp]") {
CHECK(destHandler.getTransactionStep() == DestHandler::TransactionStep::IDLE);
}
SECTION("Metadata only transfer reports a complete delivery") {
// A proxy put request is metadata only: empty file names, the request itself in a message to
// user, and no file data to wait for - so the transaction completes the moment the metadata
// lands. The delivery fields used to be left at their reset defaults on this path, reporting
// a successful transaction as "Data Incomplete" and "Discard deliberately" next to a NO_ERROR
// condition code, in the Finished PDU as well as in the log.
StringLv emptySrcName;
StringLv emptyDestName;
MetadataGenericInfo info(false, ChecksumType::NULL_CHECKSUM, Fss(0));
const TransactionSeqNum seqNum(UnsignedByteField<uint16_t>(1));
conf.sourceId = remoteId;
conf.destId = localId;
conf.mode = TransmissionMode::UNACKNOWLEDGED;
conf.seqNum = seqNum;
const MetadataPduCreator creator(conf, info, emptySrcName, emptyDestName, nullptr, 0);
REQUIRE(creator.serialize(pduBuf.data(), serLen, creator.getSerializedSize()) == OK);
auto packet =
OwnedPduPacket(creator.getPduType(), creator.getDirectiveCode(), pduBuf.data(), serLen);
destHandler.stateMachine(packet);
destHandler.stateMachineNoPacket();
REQUIRE(userMock.finishedRecvd.size() == 1);
const auto& finished = userMock.finishedRecvd.back().second;
CHECK(finished.condCode == ConditionCode::NO_ERROR);
CHECK(finished.deliveryCode == FileDeliveryCode::DATA_COMPLETE);
CHECK(finished.status == FileDeliveryStatus::FILE_STATUS_UNREPORTED);
CHECK(destHandler.getCfdpState() == CfdpState::IDLE);
}
SECTION("Empty File Transfer") {
const DestHandler::FsmResult& res = destHandler.stateMachineNoPacket();
CHECK(res.result == OK);