GCC Code Coverage Report


Directory: Svc/Ccsds/SpacePacketDeframer/
File: SpacePacketDeframer.cpp
Date: 2026-09-03 21:16:36
Exec Total Coverage
Lines: 51 56 91.1%
Functions: 5 5 100.0%
Branches: 47 59 79.7%

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 11 SpacePacketDeframer ::SpacePacketDeframer(const char* const compName) : SpacePacketDeframerComponentBase(compName) {}
20
21 22 SpacePacketDeframer ::~SpacePacketDeframer() {}
22
23 namespace {
24
25 7 bool isValidPacketVersionNumber(const SpacePacketHeader& header) {
26 7 const U16 packetIdentification = header.get_packetIdentification();
27 7 const U16 pvn = (packetIdentification & SpacePacketSubfields::PvnMask) >> SpacePacketSubfields::PvnOffset;
28 7 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 10 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
3/3
✓ Branch 4 taken 10 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 7 times.
10 if (data.getSize() <= SpacePacketHeader::SERIALIZED_SIZE) {
55
1/1
✓ Branch 5 taken 3 times.
3 this->log_WARNING_HI_InvalidPacket();
56
2/3
✓ Branch 5 taken 3 times.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
3 if (this->isConnected_errorNotify_OutputPort(0)) {
57
2/2
✓ Branch 6 taken 3 times.
✓ Branch 10 taken 3 times.
3 this->errorNotify_out(0, Svc::Ccsds::FrameError::SP_INVALID_PACKET);
58 }
59
1/1
✓ Branch 5 taken 3 times.
3 this->dataReturnOut_out(0, data, context); // Drop the packet
60 3 return;
61 }
62
63
1/1
✓ Branch 2 taken 7 times.
7 SpacePacketHeader header;
64
2/2
✓ Branch 2 taken 7 times.
✓ Branch 8 taken 7 times.
7 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 7 times.
7 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
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 6 times.
7 if (!isValidPacketVersionNumber(header)) {
76
1/1
✓ Branch 5 taken 1 times.
1 this->log_WARNING_HI_InvalidPacket();
77
2/3
✓ Branch 5 taken 1 times.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
1 if (this->isConnected_errorNotify_OutputPort(0)) {
78
2/2
✓ Branch 6 taken 1 times.
✓ Branch 10 taken 1 times.
1 this->errorNotify_out(0, Svc::Ccsds::FrameError::SP_INVALID_PACKET);
79 }
80
1/1
✓ Branch 5 taken 1 times.
1 this->dataReturnOut_out(0, data, context); // Drop the packet
81 1 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 6 const U32 pkt_length = static_cast<U32>(header.get_packetDataLength()) + 1U;
87
6/7
✓ Branch 4 taken 6 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 4 times.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 4 times.
10 if ((pkt_length > data.getSize() - SpacePacketHeader::SERIALIZED_SIZE) ||
88 4 (pkt_length > std::numeric_limits<FwSizeType>::max())) {
89
1/1
✓ Branch 4 taken 2 times.
2 FwSizeType maxDataAvailable = data.getSize() - SpacePacketHeader::SERIALIZED_SIZE;
90
1/1
✓ Branch 5 taken 2 times.
2 this->log_WARNING_HI_InvalidLength(pkt_length, maxDataAvailable);
91
2/3
✓ Branch 5 taken 2 times.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
2 if (this->isConnected_errorNotify_OutputPort(0)) {
92
2/2
✓ Branch 6 taken 2 times.
✓ Branch 10 taken 2 times.
2 this->errorNotify_out(0, Svc::Ccsds::FrameError::SP_INVALID_LENGTH);
93 }
94
1/1
✓ Branch 5 taken 2 times.
2 this->dataReturnOut_out(0, data, context); // Drop the packet
95 2 return;
96 }
97
98 4 U16 apidValue = header.get_packetIdentification() & SpacePacketSubfields::ApidMask;
99
3/3
✓ Branch 1 taken 4 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 1 times.
4 ComCfg::Apid::T apid = ComCfg::Apid::isValid(apidValue) ? static_cast<ComCfg::Apid::T>(apidValue)
100 4 : ComCfg::Apid::INVALID_UNINITIALIZED;
101
1/1
✓ Branch 2 taken 4 times.
4 ComCfg::FrameContext contextCopy = context;
102
1/1
✓ Branch 2 taken 4 times.
4 contextCopy.set_apid(apid);
103
104 // Extract secondary header flag
105 4 bool hasSecHdr = (header.get_packetIdentification() & SpacePacketSubfields::SecHdrMask) != 0;
106
1/1
✓ Branch 2 taken 4 times.
4 contextCopy.set_hasSecHdr(hasSecHdr);
107
108 // Extract sequence flags
109 4 U8 sequenceFlags = static_cast<U8>((header.get_packetSequenceControl() & SpacePacketSubfields::SeqFlagsMask) >>
110 4 SpacePacketSubfields::SeqFlagsOffset);
111
1/1
✓ Branch 2 taken 4 times.
4 contextCopy.set_sequenceFlags(sequenceFlags);
112
113 // Validate with the ApidManager that the sequence count is correct
114 4 U16 receivedSequenceCount = header.get_packetSequenceControl() & SpacePacketSubfields::SeqCountMask;
115
2/2
✓ Branch 6 taken 4 times.
✓ Branch 10 taken 4 times.
4 (void)this->validateApidSeqCount_out(0, apid, receivedSequenceCount);
116
1/1
✓ Branch 2 taken 4 times.
4 contextCopy.set_sequenceCount(receivedSequenceCount);
117
118 // Set data buffer to be of the encapsulated data: HEADER (6 bytes) | PACKET DATA
119
1/1
✓ Branch 4 taken 4 times.
4 data.advance(SpacePacketHeader::SERIALIZED_SIZE);
120
1/1
✓ Branch 4 taken 4 times.
4 data.setSize(pkt_length);
121
122
1/1
✓ Branch 5 taken 4 times.
4 this->dataOut_out(0, data, contextCopy);
123 7 }
124
125 1 void SpacePacketDeframer ::dataReturnIn_handler(FwIndexType portNum,
126 Fw::Buffer& data,
127 const ComCfg::FrameContext& context) {
128 1 this->dataReturnOut_out(0, data, context);
129 1 }
130
131 } // namespace Ccsds
132 } // namespace Svc
133