GCC Code Coverage Report


Directory: ./
File: Svc/Ccsds/CfdpManager/Types/MetadataPdu.cpp
Date: 2026-11-03 22:10:14
Exec Total Coverage
Lines: 0 108 0.0%
Functions: 0 6 0.0%
Branches: 0 67 0.0%

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