GCC Code Coverage Report


Directory: ./
File: Svc/Ccsds/CfdpManager/Types/NakPdu.cpp
Date: 2026-09-03 22:12:29
Exec Total Coverage
Lines: 0 84 0.0%
Functions: 0 8 0.0%
Branches: 0 47 0.0%

Line Branch Exec Source
1 // ======================================================================
2 // \title NakPdu.cpp
3 // \author Brian Campuzano
4 // \brief cpp file for CFDP NAK (Negative Acknowledge) PDU
5 // ======================================================================
6
7 #include <Fw/Types/Assert.hpp>
8 #include <Svc/Ccsds/CfdpManager/Types/NakPdu.hpp>
9
10 namespace Svc {
11 namespace Ccsds {
12 namespace Cfdp {
13
14 void NakPdu::initialize(PduDirection direction,
15 Cfdp::Class::T txmMode,
16 EntityId sourceEid,
17 TransactionSeq transactionSeq,
18 EntityId destEid,
19 FileSize scopeStart,
20 FileSize scopeEnd) {
21 // Initialize header with PduTypeEnum::NEGATIVE_ACK type
22 this->m_header.initialize(PduTypeEnum::NEGATIVE_ACK, direction, txmMode, sourceEid, transactionSeq, destEid);
23
24 this->m_scopeStart = scopeStart;
25 this->m_scopeEnd = scopeEnd;
26 this->m_numSegments = 0;
27 }
28
29 bool NakPdu::addSegment(FileSize offsetStart, FileSize offsetEnd) {
30 if (this->m_numSegments >= NakMaxSegments) {
31 return false;
32 }
33 this->m_segments[this->m_numSegments].offsetStart = offsetStart;
34 this->m_segments[this->m_numSegments].offsetEnd = offsetEnd;
35 this->m_numSegments++;
36 return true;
37 }
38
39 void NakPdu::clearSegments() {
40 this->m_numSegments = 0;
41 }
42
43 U32 NakPdu::getBufferSize() const {
44 U32 size = this->m_header.getBufferSize();
45
46 // Directive code: 1 byte (FileDirective::FILE_DIRECTIVE_NAK)
47 // Scope start: sizeof(FileSize) bytes
48 // Scope end: sizeof(FileSize) bytes
49 // Segment requests: m_numSegments * (2 * sizeof(FileSize)) bytes
50 size += static_cast<U32>(sizeof(U8) + sizeof(FileSize) + sizeof(FileSize));
51 size += static_cast<U32>(this->m_numSegments * (sizeof(FileSize) + sizeof(FileSize)));
52
53 return size;
54 }
55
56 Fw::SerializeStatus NakPdu::serializeTo(Fw::SerialBufferBase& buffer, Fw::Endianness mode) const {
57 return this->toSerialBuffer(buffer);
58 }
59
60 Fw::SerializeStatus NakPdu::deserializeFrom(Fw::SerialBufferBase& buffer, Fw::Endianness mode) {
61 // Deserialize header first
62 Fw::SerializeStatus status = this->m_header.fromSerialBuffer(buffer);
63 if (status != Fw::FW_SERIALIZE_OK) {
64 return status;
65 }
66
67 // Validate this is a directive PDU (not file data)
68 if (this->m_header.m_pduType != PduType::PDU_TYPE_DIRECTIVE) {
69 return Fw::FW_DESERIALIZE_TYPE_MISMATCH;
70 }
71
72 // Validate directive code
73 U8 directiveCode;
74 status = buffer.deserializeTo(directiveCode);
75 if (status != Fw::FW_SERIALIZE_OK) {
76 return status;
77 }
78 if (directiveCode != static_cast<U8>(FileDirective::FILE_DIRECTIVE_NAK)) {
79 return Fw::FW_DESERIALIZE_TYPE_MISMATCH;
80 }
81
82 // Now set the type to PduTypeEnum::NEGATIVE_ACK since we've validated it
83 this->m_header.m_type = PduTypeEnum::NEGATIVE_ACK;
84
85 // Deserialize the NAK body
86 return this->fromSerialBuffer(buffer);
87 }
88
89 Fw::SerializeStatus NakPdu::toSerialBuffer(Fw::SerialBufferBase& serialBuffer) const {
90 FW_ASSERT(this->m_header.m_type == PduTypeEnum::NEGATIVE_ACK);
91
92 // Calculate PDU data length (everything after header)
93 U32 dataLength = this->getBufferSize() - this->m_header.getBufferSize();
94
95 // Update header with data length
96 PduHeader headerCopy = this->m_header;
97 headerCopy.setPduDataLength(static_cast<U16>(dataLength));
98
99 // Serialize header
100 Fw::SerializeStatus status = headerCopy.toSerialBuffer(serialBuffer);
101 if (status != Fw::FW_SERIALIZE_OK) {
102 return status;
103 }
104
105 // Directive code (NAK = 8)
106 U8 directiveCodeByte = static_cast<U8>(FileDirective::FILE_DIRECTIVE_NAK);
107 status = serialBuffer.serializeFrom(directiveCodeByte);
108 if (status != Fw::FW_SERIALIZE_OK) {
109 return status;
110 }
111
112 // Scope start (file offset)
113 status = serialBuffer.serializeFrom(this->m_scopeStart);
114 if (status != Fw::FW_SERIALIZE_OK) {
115 return status;
116 }
117
118 // Scope end (file offset)
119 status = serialBuffer.serializeFrom(this->m_scopeEnd);
120 if (status != Fw::FW_SERIALIZE_OK) {
121 return status;
122 }
123
124 // Serialize segment requests
125 for (U8 i = 0; i < this->m_numSegments; i++) {
126 // Segment start offset
127 status = serialBuffer.serializeFrom(this->m_segments[i].offsetStart);
128 if (status != Fw::FW_SERIALIZE_OK) {
129 return status;
130 }
131
132 // Segment end offset
133 status = serialBuffer.serializeFrom(this->m_segments[i].offsetEnd);
134 if (status != Fw::FW_SERIALIZE_OK) {
135 return status;
136 }
137 }
138
139 return Fw::FW_SERIALIZE_OK;
140 }
141
142 Fw::SerializeStatus NakPdu::fromSerialBuffer(Fw::SerialBufferBase& serialBuffer) {
143 FW_ASSERT(this->m_header.m_type == PduTypeEnum::NEGATIVE_ACK);
144
145 // Directive code already read by fromBuffer()
146
147 // Scope start (file offset)
148 Fw::SerializeStatus status = serialBuffer.deserializeTo(this->m_scopeStart);
149 if (status != Fw::FW_SERIALIZE_OK) {
150 return status;
151 }
152
153 // Scope end (file offset)
154 status = serialBuffer.deserializeTo(this->m_scopeEnd);
155 if (status != Fw::FW_SERIALIZE_OK) {
156 return status;
157 }
158
159 // Calculate number of segment requests from remaining buffer size
160 // Each segment is 2 * sizeof(FileSize) bytes
161 Fw::Serializable::SizeType remainingBytes = serialBuffer.getDeserializeSizeLeft();
162 U32 segmentSize = static_cast<U32>(sizeof(FileSize) + sizeof(FileSize));
163 U32 numSegsCalculated = static_cast<U32>(remainingBytes / segmentSize);
164 this->m_numSegments = static_cast<U8>(numSegsCalculated);
165
166 // Limit to max segments
167 if (this->m_numSegments > NakMaxSegments) {
168 this->m_numSegments = NakMaxSegments;
169 }
170
171 // Deserialize segment requests
172 for (U8 i = 0; i < this->m_numSegments; i++) {
173 // Segment start offset
174 status = serialBuffer.deserializeTo(this->m_segments[i].offsetStart);
175 if (status != Fw::FW_SERIALIZE_OK) {
176 return status;
177 }
178
179 // Segment end offset
180 status = serialBuffer.deserializeTo(this->m_segments[i].offsetEnd);
181 if (status != Fw::FW_SERIALIZE_OK) {
182 return status;
183 }
184 }
185
186 return Fw::FW_SERIALIZE_OK;
187 }
188
189 } // namespace Cfdp
190 } // namespace Ccsds
191 } // namespace Svc
192