GCC Code Coverage Report


Directory: /home/runner/work/fprime/fprime/Svc/Ccsds/SpacePacketDeframer/
File: SpacePacketDeframer.cpp
Date: 2026-09-03 22:13:26
Exec Total Coverage
Lines: 35 56 62.5%
Functions: 5 5 100.0%
Branches: 23 59 39.0%

Line Branch Exec Source
1 // ======================================================================
2 // \title SpacePacketDeframer.cpp
3 // \author thomas-bc
4 // \brief cpp file for SpacePacketDeframer component implementation class
5 // ======================================================================
6
7 #include "Svc/Ccsds/SpacePacketDeframer/SpacePacketDeframer.hpp"
8 #include "Svc/Ccsds/Types/FppConstantsAc.hpp"
9 #include "Svc/Ccsds/Types/SpacePacketHeaderSerializableAc.hpp"
10
11 namespace Svc {
12
13 namespace Ccsds {
14
15 // ----------------------------------------------------------------------
16 // Component construction and destruction
17 // ----------------------------------------------------------------------
18
19 1 SpacePacketDeframer ::SpacePacketDeframer(const char* const compName) : SpacePacketDeframerComponentBase(compName) {}
20
21 2 SpacePacketDeframer ::~SpacePacketDeframer() {}
22
23 namespace {
24
25 146 bool isValidPacketVersionNumber(const SpacePacketHeader& header) {
26 146 const U16 packetIdentification = header.get_packetIdentification();
27 146 const U16 pvn = (packetIdentification & SpacePacketSubfields::PvnMask) >> SpacePacketSubfields::PvnOffset;
28 146 return pvn == static_cast<U16>(ComCfg::Pvn::SPACE_PACKET_PROTOCOL);
29 }
30
31 } // namespace
32
33 // ----------------------------------------------------------------------
34 // Handler implementations for typed input ports
35 // ----------------------------------------------------------------------
36
37 146 void SpacePacketDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) {
38 // ################################
39 // CCSDS SpacePacket Format:
40 // 6 octets - Primary Header
41 // 0-65536 octets - Data Field (with optional secondary header)
42
43 // CCSDS SpacePacket Primary Header:
44 // 3b - 000 - (PVN) Packet Version Number
45 // 1b - 0/1 - (PT) Packet Type
46 // 1b - 0/1 - (SHF) Secondary Header Flag
47 // 11b - n/a - (APID) Application Process ID
48 // 2b - 00/01/10/11 - Sequence Flag
49 // 14b - n/a - Sequence Count
50 // 16b - n/a - Packet Data Length
51 // ################################
52
53 // Check size and drop packets that are too-small
54
2/3
✓ Branch 1 taken 146 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 146 times.
146 if (data.getSize() <= SpacePacketHeader::SERIALIZED_SIZE) {
55 this->log_WARNING_HI_InvalidPacket();
56 if (this->isConnected_errorNotify_OutputPort(0)) {
57 this->errorNotify_out(0, Svc::Ccsds::FrameError::SP_INVALID_PACKET);
58 }
59 this->dataReturnOut_out(0, data, context); // Drop the packet
60 return;
61 }
62
63
1/1
✓ Branch 1 taken 146 times.
146 SpacePacketHeader header;
64
2/2
✓ Branch 1 taken 146 times.
✓ Branch 4 taken 146 times.
146 Fw::SerializeStatus status = data.getDeserializer().deserializeTo(header);
65 // Deserialization can still fail if the buffer is malformed despite passing the size check
66
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
146 if (status != Fw::FW_SERIALIZE_OK) {
67 this->log_WARNING_HI_InvalidPacket();
68 if (this->isConnected_errorNotify_OutputPort(0)) {
69 this->errorNotify_out(0, Svc::Ccsds::FrameError::SP_INVALID_PACKET);
70 }
71 this->dataReturnOut_out(0, data, context); // Drop the packet
72 return;
73 }
74
75
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 146 times.
146 if (!isValidPacketVersionNumber(header)) {
76 this->log_WARNING_HI_InvalidPacket();
77 if (this->isConnected_errorNotify_OutputPort(0)) {
78 this->errorNotify_out(0, Svc::Ccsds::FrameError::SP_INVALID_PACKET);
79 }
80 this->dataReturnOut_out(0, data, context); // Drop the packet
81 return;
82 }
83
84 // Widen to U32 before adding 1 to prevent U16 truncation to 0 when packetDataLength == 0xFFFF (max U16 value).
85 // This is a undefined behavior condition in C++.
86 146 const U32 pkt_length = static_cast<U32>(header.get_packetDataLength()) + 1U;
87
4/7
✓ Branch 1 taken 146 times.
✓ Branch 3 taken 146 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 146 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 146 times.
292 if ((pkt_length > data.getSize() - SpacePacketHeader::SERIALIZED_SIZE) ||
88 146 (pkt_length > std::numeric_limits<FwSizeType>::max())) {
89 FwSizeType maxDataAvailable = data.getSize() - SpacePacketHeader::SERIALIZED_SIZE;
90 this->log_WARNING_HI_InvalidLength(pkt_length, maxDataAvailable);
91 if (this->isConnected_errorNotify_OutputPort(0)) {
92 this->errorNotify_out(0, Svc::Ccsds::FrameError::SP_INVALID_LENGTH);
93 }
94 this->dataReturnOut_out(0, data, context); // Drop the packet
95 return;
96 }
97
98 146 U16 apidValue = header.get_packetIdentification() & SpacePacketSubfields::ApidMask;
99
2/3
✓ Branch 1 taken 146 times.
✓ Branch 3 taken 146 times.
✗ Branch 4 not taken.
146 ComCfg::Apid::T apid = ComCfg::Apid::isValid(apidValue) ? static_cast<ComCfg::Apid::T>(apidValue)
100 146 : ComCfg::Apid::INVALID_UNINITIALIZED;
101
1/1
✓ Branch 1 taken 146 times.
146 ComCfg::FrameContext contextCopy = context;
102
1/1
✓ Branch 1 taken 146 times.
146 contextCopy.set_apid(apid);
103
104 // Extract secondary header flag
105 146 bool hasSecHdr = (header.get_packetIdentification() & SpacePacketSubfields::SecHdrMask) != 0;
106
1/1
✓ Branch 1 taken 146 times.
146 contextCopy.set_hasSecHdr(hasSecHdr);
107
108 // Extract sequence flags
109 146 U8 sequenceFlags = static_cast<U8>((header.get_packetSequenceControl() & SpacePacketSubfields::SeqFlagsMask) >>
110 146 SpacePacketSubfields::SeqFlagsOffset);
111
1/1
✓ Branch 1 taken 146 times.
146 contextCopy.set_sequenceFlags(sequenceFlags);
112
113 // Validate with the ApidManager that the sequence count is correct
114 146 U16 receivedSequenceCount = header.get_packetSequenceControl() & SpacePacketSubfields::SeqCountMask;
115
2/2
✓ Branch 1 taken 146 times.
✓ Branch 4 taken 146 times.
146 (void)this->validateApidSeqCount_out(0, apid, receivedSequenceCount);
116
1/1
✓ Branch 1 taken 146 times.
146 contextCopy.set_sequenceCount(receivedSequenceCount);
117
118 // Set data buffer to be of the encapsulated data: HEADER (6 bytes) | PACKET DATA
119
1/1
✓ Branch 1 taken 146 times.
146 data.advance(SpacePacketHeader::SERIALIZED_SIZE);
120
1/1
✓ Branch 1 taken 146 times.
146 data.setSize(pkt_length);
121
122
1/1
✓ Branch 1 taken 146 times.
146 this->dataOut_out(0, data, contextCopy);
123 146 }
124
125 146 void SpacePacketDeframer ::dataReturnIn_handler(FwIndexType portNum,
126 Fw::Buffer& data,
127 const ComCfg::FrameContext& context) {
128 146 this->dataReturnOut_out(0, data, context);
129 146 }
130
131 } // namespace Ccsds
132 } // namespace Svc
133