# CFDP acknowledged mode (class 2)
## Summary
Both CFDP handlers implement class 2. Before this, `BUSY_CLASS_2_ACKED` was a stub on the
destination side and the source handler ignored every incoming PDU.
Destination handler:
```diff
RECEIVING_FILE_DATA_PDUS track gaps per received segment
EOF
+ SENDING_ACK_PDU ACK(EOF) before the checksum pass
+ WAITING_FOR_MISSING_DATA deferred NAK sequence, NAK timer, check timer
TRANSFER_COMPLETION
SENDING_FINISHED_PDU
+ WAITING_FOR_FINISHED_ACK positive ACK timer, retransmit Finished
```
Source handler:
```diff
SENDING_FILE_DATA
SENDING_EOF
+WAIT_FOR_ACK positive ACK timer, answer NAKs with retransmissions
WAIT_FOR_FINISH now actually parses the Finished PDU
+ send ACK(Finished)
NOTICE_OF_COMPLETION reports the received condition and delivery codes
```
Behaviour worth knowing:
- Lost metadata is recovered: the transaction starts from the first file data or EOF PDU and
requests the metadata with a NAK of scope 0..0.
- An EOF for a transaction that is already finished is still acknowledged.
- The NAK and check limits count expirations without progress. Missing data arriving resets them
(CFDP 4.6.4.7).
- A class 2 metadata only transaction (a proxy put request) waits for its EOF, so the Finished PDU
never overtakes the EOF ACK.
- NAK segment requests that do not fit one PDU are carried into the next PDU of the sequence.
Fixes found along the way, all of them also affect class 1:
- Metadata, NAK and Finished readers take the PDU CRC out of the parsed range. Before, any PDU
with a CRC and options, segment requests or filestore responses failed with
`INVALID_TLV_TYPE`.
- A Cancel EOF is parsed and ends the transaction. It was dropped as unparseable.
- `PduSenderIF::sendPdu()` failures are no longer treated as sent. Both handlers retry, the
Finished PDU with a bounded number of attempts.
- PDUs are filtered by transaction ID, so a late PDU from an earlier transaction cannot drive the
current one.
- A metadata only transaction reports `DATA_COMPLETE` instead of the "Data Incomplete" defaults.
- `arrayprinter` prints in fixed chunks instead of a stack buffer sized from the input. Dumping a
12 KB buffer overflowed an 8 KB task.
- Metadata options beyond the option array are rejected instead of written past it.
New configuration, all with defaults:
```text
RemoteEntityCfg positiveAckTimerIntervalMs, positiveAckTimerExpirationLimit,
nakTimerIntervalMs, nakTimerExpirationLimit, immediateNakMode,
checkLimit, checkTimerIntervalMs
DestHandlerParams maxSegmentRequestsPerNakPdu, maxFinishedPduSendAttempts
returnvalue cfdp::TRANSMISSION_MODE_NOT_SUPPORTED
```
## Evidence
- **Before:** an acknowledged uplink failed after about 40 s. The sender retransmitted EOF to
`POSITIVE_ACK_LIMIT_REACHED` because the destination never sent an ACK. An acknowledged put
request left the source handler busy for good.
**After:** `fsfw-tests "[cfdp]"` passes, 26 test cases. New sections include:
```text
CFDP Dest Handler Acknowledged
Nominal acknowledged transfer
Dropped file data PDU is recovered via NAK
Dropped metadata PDU is requested with a scope 0 to 0 NAK
Finished PDU is retransmitted on positive ACK timeout
NAK limit reached cancels the transaction
Retransmitted data resets the NAK and check limits
Metadata only transaction sends Finished after the EOF ACK
EOF PDU for an inactive transaction is acknowledged
Cancel EOF is parsed, acknowledged and ends the transaction
A Finished ACK for a different transaction is ignored
CFDP Source Handler Acknowledged
Nominal acknowledged transfer
EOF PDU is retransmitted on positive ACK timeout
NAK PDU drives segment retransmission
NAK PDU of scope 0 to 0 retransmits the metadata PDU
A NAK keeps the inactivity guard from firing during recovery
Finished PDU condition code is reported instead of a hardcoded success
Finished / Metadata / NAK PDU with CRC
```
Plus class 1 sections for send failures, Cancel EOF and metadata only transfers. The last two
destination fixes were checked with their tests failing before the fix.
- **Hardware:** SOURCE flatsat, iOBC, over the maintenance port with a proxy dropping 15 % of the
packets in each direction. A 200 kB uplink and the downlink of the same file both completed
with `NO_ERROR`, and the downlinked file was byte identical to the original.
## Merge Danger
**Door:** two-way
Plain code changes, no stored data or formats change. A revert restores the old behaviour.
**Blast Radius:** CFDP users
Every mission using the CFDP handlers gets the class 1 fixes too: send failures are retried
instead of dropped, a Cancel EOF ends the transaction, and CRC-bearing PDUs with variable length
tails now parse. Existing `RemoteEntityCfg` setups compile unchanged, the new fields default to
values that leave class 1 alone. Not covered: the PDU creators still cannot size a CRC-bearing PDU,
so `crcOnTransmission` has to stay false as before.
---------
Co-authored-by: Tobias Baumgartl <tobias.baumgartl@ksat-stuttgart.de>
Reviewed-on: #73