GCC Code Coverage Report


Directory: ./
File: Svc/Ccsds/CfdpManager/Types/MetadataPdu.cpp
Date: 2026-09-03 21:13:48
Exec Total Coverage
Lines: 93 114 81.6%
Functions: 6 6 100.0%
Branches: 46 67 68.7%

Line Branch Exec Source
1 // ======================================================================
2 // \title MetadataPdu.cpp
3 // \author Brian Campuzano
4 // \brief cpp file for CFDP Metadata PDU
5 // ======================================================================
6
7 #include <Fw/Types/Assert.hpp>
8 #include <Fw/Types/StringUtils.hpp>
9 #include <Svc/Ccsds/CfdpManager/Types/MetadataPdu.hpp>
10 #include <config/CfdpCfg.hpp>
11
12 namespace Svc {
13 namespace Ccsds {
14 namespace Cfdp {
15
16 100 void MetadataPdu::initialize(PduDirection direction,
17 Cfdp::Class::T txmMode,
18 EntityId sourceEid,
19 TransactionSeq transactionSeq,
20 EntityId destEid,
21 FileSize fileSize,
22 const Fw::String& sourceFilename,
23 const Fw::String& destFilename,
24 ChecksumType checksumType,
25 U8 closureRequested) {
26 100 this->m_header.initialize(PduTypeEnum::METADATA, direction, txmMode, sourceEid, transactionSeq, destEid);
27
28 100 this->m_fileSize = fileSize;
29
30 // Enforce MaxFilePathSize for source filename
31 100 FwSizeType srcLen = sourceFilename.length();
32 100 FW_ASSERT(srcLen <= MaxFilePathSize, static_cast<FwAssertArgType>(srcLen), MaxFilePathSize);
33 100 this->m_sourceFilename = sourceFilename;
34
35 // Enforce MaxFilePathSize for destination filename
36 100 FwSizeType dstLen = destFilename.length();
37 100 FW_ASSERT(dstLen <= MaxFilePathSize, static_cast<FwAssertArgType>(dstLen), MaxFilePathSize);
38 100 this->m_destFilename = destFilename;
39
40 100 this->m_checksumType = checksumType;
41 100 this->m_closureRequested = closureRequested;
42 100 }
43
44 191 U32 MetadataPdu::getBufferSize() const {
45 191 U32 size = this->m_header.getBufferSize();
46
47 // Directive code: 1 byte
48 // Segmentation control byte (includes closure requested and checksum type): 1 byte
49 // File size: variable
50 191 size += static_cast<U32>(sizeof(U8) + sizeof(U8) + sizeof(FileSize));
51
52 // Source filename LV: length(1) + value(n)
53 191 size += 1 + static_cast<U32>(this->m_sourceFilename.length());
54
55 // Dest filename LV: length(1) + value(n)
56 191 size += 1 + static_cast<U32>(this->m_destFilename.length());
57
58 191 return size;
59 }
60
61 99 Fw::SerializeStatus MetadataPdu::serializeTo(Fw::SerialBufferBase& buffer, Fw::Endianness mode) const {
62 99 return this->toSerialBuffer(buffer);
63 }
64
65 88 Fw::SerializeStatus MetadataPdu::deserializeFrom(Fw::SerialBufferBase& buffer, Fw::Endianness mode) {
66 // Deserialize header first
67
1/1
✓ Branch 4 taken 88 times.
88 Fw::SerializeStatus status = this->m_header.fromSerialBuffer(buffer);
68
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
88 if (status != Fw::FW_SERIALIZE_OK) {
69 return status;
70 }
71
72 // Validate this is a directive PDU (not file data)
73
1/2
✗ Branch 5 not taken.
✓ Branch 6 taken 88 times.
88 if (this->m_header.m_pduType != PduType::PDU_TYPE_DIRECTIVE) {
74 return Fw::FW_DESERIALIZE_TYPE_MISMATCH;
75 }
76
77 // Validate directive code
78 88 U8 directiveCode;
79
1/1
✓ Branch 7 taken 88 times.
88 status = buffer.deserializeTo(directiveCode);
80
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
88 if (status != Fw::FW_SERIALIZE_OK) {
81 return status;
82 }
83
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
88 if (directiveCode != static_cast<U8>(FileDirective::FILE_DIRECTIVE_METADATA)) {
84 return Fw::FW_DESERIALIZE_TYPE_MISMATCH;
85 }
86
87 // Now set the type to PduTypeEnum::METADATA since we've validated it
88 88 this->m_header.m_type = PduTypeEnum::METADATA;
89
90 // Deserialize the metadata body
91
1/1
✓ Branch 4 taken 88 times.
88 return this->fromSerialBuffer(buffer);
92 }
93
94 99 Fw::SerializeStatus MetadataPdu::toSerialBuffer(Fw::SerialBufferBase& serialBuffer) const {
95 99 FW_ASSERT(this->m_header.m_type == PduTypeEnum::METADATA);
96
97 // Calculate PDU data length (everything after header)
98
2/2
✓ Branch 7 taken 99 times.
✓ Branch 15 taken 99 times.
99 U32 dataLength = this->getBufferSize() - this->m_header.getBufferSize();
99
100 // Update header with data length
101 99 PduHeader headerCopy = this->m_header;
102 99 headerCopy.setPduDataLength(static_cast<U16>(dataLength));
103
104 // Serialize header
105
1/1
✓ Branch 1 taken 99 times.
99 Fw::SerializeStatus status = headerCopy.toSerialBuffer(serialBuffer);
106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 if (status != Fw::FW_SERIALIZE_OK) {
107 return status;
108 }
109
110 // Directive code (METADATA = 7)
111 99 U8 directiveCode = static_cast<U8>(FileDirective::FILE_DIRECTIVE_METADATA);
112
1/1
✓ Branch 7 taken 99 times.
99 status = serialBuffer.serializeFrom(directiveCode);
113
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 if (status != Fw::FW_SERIALIZE_OK) {
114 return status;
115 }
116
117 // Segmentation control byte
118 // bit 7: closure_requested
119 // bits 6-4: reserved (000b)
120 // bits 3-0: checksum_type
121 99 U8 segmentationControl = 0;
122 99 segmentationControl =
123 99 static_cast<U8>(segmentationControl | static_cast<U8>((this->m_closureRequested & 0x01U) << 7));
124 99 segmentationControl = static_cast<U8>(segmentationControl | (static_cast<U8>(this->m_checksumType) & 0x0FU));
125
126
1/1
✓ Branch 7 taken 99 times.
99 status = serialBuffer.serializeFrom(segmentationControl);
127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 if (status != Fw::FW_SERIALIZE_OK) {
128 return status;
129 }
130
131 // File size (FileSize)
132
1/1
✓ Branch 11 taken 99 times.
99 status = serialBuffer.serializeFrom(this->m_fileSize);
133
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 if (status != Fw::FW_SERIALIZE_OK) {
134 return status;
135 }
136
137 // Source filename LV
138
1/1
✓ Branch 11 taken 99 times.
99 U8 sourceFilenameLength = static_cast<U8>(this->m_sourceFilename.length());
139
1/1
✓ Branch 7 taken 99 times.
99 status = serialBuffer.serializeFrom(sourceFilenameLength);
140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 if (status != Fw::FW_SERIALIZE_OK) {
141 return status;
142 }
143
144 // Serialize source filename bytes without length prefix
145
1/1
✓ Branch 18 taken 99 times.
99 status = serialBuffer.serializeFrom(reinterpret_cast<const U8*>(this->m_sourceFilename.toChar()),
146 sourceFilenameLength, Fw::Serialization::OMIT_LENGTH);
147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 if (status != Fw::FW_SERIALIZE_OK) {
148 return status;
149 }
150
151 // Destination filename LV
152
1/1
✓ Branch 11 taken 99 times.
99 U8 destFilenameLength = static_cast<U8>(this->m_destFilename.length());
153
1/1
✓ Branch 7 taken 99 times.
99 status = serialBuffer.serializeFrom(destFilenameLength);
154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 if (status != Fw::FW_SERIALIZE_OK) {
155 return status;
156 }
157
158 // Serialize dest filename bytes without length prefix
159
1/1
✓ Branch 18 taken 99 times.
99 status = serialBuffer.serializeFrom(reinterpret_cast<const U8*>(this->m_destFilename.toChar()), destFilenameLength,
160 Fw::Serialization::OMIT_LENGTH);
161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 if (status != Fw::FW_SERIALIZE_OK) {
162 return status;
163 }
164
165 99 return Fw::FW_SERIALIZE_OK;
166 }
167
168 88 Fw::SerializeStatus MetadataPdu::fromSerialBuffer(Fw::SerialBufferBase& serialBuffer) {
169 88 FW_ASSERT(this->m_header.m_type == PduTypeEnum::METADATA);
170
171 // Directive code already read by union wrapper
172
173 // Segmentation control byte
174 88 U8 segmentationControl;
175
1/1
✓ Branch 7 taken 88 times.
88 Fw::SerializeStatus status = serialBuffer.deserializeTo(segmentationControl);
176
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
88 if (status != Fw::FW_SERIALIZE_OK) {
177 return status;
178 }
179
180 88 this->m_closureRequested = (segmentationControl >> 7) & 0x01;
181 88 U8 checksumTypeVal = segmentationControl & 0x0F;
182 88 this->m_checksumType = static_cast<ChecksumType>(checksumTypeVal);
183
184 // File size
185
1/1
✓ Branch 10 taken 88 times.
88 status = serialBuffer.deserializeTo(this->m_fileSize);
186
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
88 if (status != Fw::FW_SERIALIZE_OK) {
187 return status;
188 }
189
190 // Source filename LV
191 88 U8 sourceFilenameLength;
192
1/1
✓ Branch 7 taken 88 times.
88 status = serialBuffer.deserializeTo(sourceFilenameLength);
193
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
88 if (status != Fw::FW_SERIALIZE_OK) {
194 return status;
195 }
196
197 // Validate filename length against MaxFilePathSize
198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
88 if (sourceFilenameLength > MaxFilePathSize) {
199 return Fw::FW_DESERIALIZE_SIZE_MISMATCH;
200 }
201
202 // Validate filename is not empty
203
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
88 if (sourceFilenameLength == 0) {
204 return Fw::FW_DESERIALIZE_SIZE_MISMATCH;
205 }
206
207 // Read filename into temporary buffer
208 88 U8 sourceFilenameBuffer[MaxFilePathSize + 1];
209 88 FwSizeType actualLength = sourceFilenameLength;
210
1/1
✓ Branch 7 taken 88 times.
88 status = serialBuffer.deserializeTo(sourceFilenameBuffer, actualLength, Fw::Serialization::OMIT_LENGTH);
211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
88 if (status != Fw::FW_SERIALIZE_OK) {
212 return status;
213 }
214 // Null-terminate before assigning to Fw::String
215 88 sourceFilenameBuffer[sourceFilenameLength] = '\0';
216
1/1
✓ Branch 6 taken 88 times.
88 this->m_sourceFilename = reinterpret_cast<const CHAR*>(sourceFilenameBuffer);
217
218 // Destination filename LV
219 88 U8 destFilenameLength;
220
1/1
✓ Branch 7 taken 88 times.
88 status = serialBuffer.deserializeTo(destFilenameLength);
221
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
88 if (status != Fw::FW_SERIALIZE_OK) {
222 return status;
223 }
224
225 // Validate filename length against MaxFilePathSize
226
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
88 if (destFilenameLength > MaxFilePathSize) {
227 return Fw::FW_DESERIALIZE_SIZE_MISMATCH;
228 }
229
230 // Validate filename is not empty
231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
88 if (destFilenameLength == 0) {
232 return Fw::FW_DESERIALIZE_SIZE_MISMATCH;
233 }
234
235 // Read filename into temporary buffer
236 88 U8 destFilenameBuffer[MaxFilePathSize + 1];
237 88 actualLength = destFilenameLength;
238
1/1
✓ Branch 7 taken 88 times.
88 status = serialBuffer.deserializeTo(destFilenameBuffer, actualLength, Fw::Serialization::OMIT_LENGTH);
239
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 87 times.
88 if (status != Fw::FW_SERIALIZE_OK) {
240 1 return status;
241 }
242 // Null-terminate before assigning to Fw::String
243 87 destFilenameBuffer[destFilenameLength] = '\0';
244
1/1
✓ Branch 6 taken 87 times.
87 this->m_destFilename = reinterpret_cast<const CHAR*>(destFilenameBuffer);
245
246 87 return Fw::FW_SERIALIZE_OK;
247 }
248
249 } // namespace Cfdp
250 } // namespace Ccsds
251 } // namespace Svc
252