F´ Flight Software - C/C++ Documentation
A framework for building embedded system applications to NASA flight quality standards.
MetadataPdu.cpp
Go to the documentation of this file.
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>
10 #include <config/CfdpCfg.hpp>
11 
12 namespace Svc {
13 namespace Ccsds {
14 namespace Cfdp {
15 
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 
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 
62  return this->toSerialBuffer(buffer);
63 }
64 
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) {
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)) {
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  // Segmentation control byte
118  // bit 7: closure_requested
119  // bits 6-4: reserved (000b)
120  // bits 3-0: checksum_type
121  U8 segmentationControl = 0;
122  segmentationControl =
123  static_cast<U8>(segmentationControl | static_cast<U8>((this->m_closureRequested & 0x01U) << 7));
124  segmentationControl = static_cast<U8>(segmentationControl | (static_cast<U8>(this->m_checksumType) & 0x0FU));
125 
126  status = serialBuffer.serializeFrom(segmentationControl);
127  if (status != Fw::FW_SERIALIZE_OK) {
128  return status;
129  }
130 
131  // File size (FileSize)
132  status = serialBuffer.serializeFrom(this->m_fileSize);
133  if (status != Fw::FW_SERIALIZE_OK) {
134  return status;
135  }
136 
137  // Source filename LV
138  U8 sourceFilenameLength = static_cast<U8>(this->m_sourceFilename.length());
139  status = serialBuffer.serializeFrom(sourceFilenameLength);
140  if (status != Fw::FW_SERIALIZE_OK) {
141  return status;
142  }
143 
144  // Serialize source filename bytes without length prefix
145  status = serialBuffer.serializeFrom(reinterpret_cast<const U8*>(this->m_sourceFilename.toChar()),
146  sourceFilenameLength, Fw::Serialization::OMIT_LENGTH);
147  if (status != Fw::FW_SERIALIZE_OK) {
148  return status;
149  }
150 
151  // Destination filename LV
152  U8 destFilenameLength = static_cast<U8>(this->m_destFilename.length());
153  status = serialBuffer.serializeFrom(destFilenameLength);
154  if (status != Fw::FW_SERIALIZE_OK) {
155  return status;
156  }
157 
158  // Serialize dest filename bytes without length prefix
159  status = serialBuffer.serializeFrom(reinterpret_cast<const U8*>(this->m_destFilename.toChar()), destFilenameLength,
161  if (status != Fw::FW_SERIALIZE_OK) {
162  return status;
163  }
164 
165  return Fw::FW_SERIALIZE_OK;
166 }
167 
168 Fw::SerializeStatus MetadataPdu::fromSerialBuffer(Fw::SerialBufferBase& serialBuffer) {
169  FW_ASSERT(this->m_header.m_type == PduTypeEnum::METADATA);
170 
171  // Directive code already read by union wrapper
172 
173  // Segmentation control byte
174  U8 segmentationControl;
175  Fw::SerializeStatus status = serialBuffer.deserializeTo(segmentationControl);
176  if (status != Fw::FW_SERIALIZE_OK) {
177  return status;
178  }
179 
180  this->m_closureRequested = (segmentationControl >> 7) & 0x01;
181  U8 checksumTypeVal = segmentationControl & 0x0F;
182  this->m_checksumType = static_cast<ChecksumType>(checksumTypeVal);
183 
184  // File size
185  status = serialBuffer.deserializeTo(this->m_fileSize);
186  if (status != Fw::FW_SERIALIZE_OK) {
187  return status;
188  }
189 
190  // Source filename LV
191  U8 sourceFilenameLength;
192  status = serialBuffer.deserializeTo(sourceFilenameLength);
193  if (status != Fw::FW_SERIALIZE_OK) {
194  return status;
195  }
196 
197  // Validate filename length against MaxFilePathSize
198  if (sourceFilenameLength > MaxFilePathSize) {
200  }
201 
202  // Validate filename is not empty
203  if (sourceFilenameLength == 0) {
205  }
206 
207  // Read filename into temporary buffer
208  U8 sourceFilenameBuffer[MaxFilePathSize + 1];
209  FwSizeType actualLength = sourceFilenameLength;
210  status = serialBuffer.deserializeTo(sourceFilenameBuffer, actualLength, Fw::Serialization::OMIT_LENGTH);
211  if (status != Fw::FW_SERIALIZE_OK) {
212  return status;
213  }
214  // Null-terminate before assigning to Fw::String
215  sourceFilenameBuffer[sourceFilenameLength] = '\0';
216  this->m_sourceFilename = reinterpret_cast<const CHAR*>(sourceFilenameBuffer);
217 
218  // Destination filename LV
219  U8 destFilenameLength;
220  status = serialBuffer.deserializeTo(destFilenameLength);
221  if (status != Fw::FW_SERIALIZE_OK) {
222  return status;
223  }
224 
225  // Validate filename length against MaxFilePathSize
226  if (destFilenameLength > MaxFilePathSize) {
228  }
229 
230  // Validate filename is not empty
231  if (destFilenameLength == 0) {
233  }
234 
235  // Read filename into temporary buffer
236  U8 destFilenameBuffer[MaxFilePathSize + 1];
237  actualLength = destFilenameLength;
238  status = serialBuffer.deserializeTo(destFilenameBuffer, actualLength, Fw::Serialization::OMIT_LENGTH);
239  if (status != Fw::FW_SERIALIZE_OK) {
240  return status;
241  }
242  // Null-terminate before assigning to Fw::String
243  destFilenameBuffer[destFilenameLength] = '\0';
244  this->m_destFilename = reinterpret_cast<const CHAR*>(destFilenameBuffer);
245 
246  return Fw::FW_SERIALIZE_OK;
247 }
248 
249 } // namespace Cfdp
250 } // namespace Ccsds
251 } // namespace Svc
Serialization/Deserialization operation was successful.
PlatformSizeType FwSizeType
U32 EntityId
Entity id size.
char CHAR
Definition: BasicTypes.h:60
void initialize(PduTypeEnum::T type, PduDirection direction, Cfdp::Class::T txmMode, EntityId sourceEid, TransactionSeq transactionSeq, EntityId destEid)
Initialize a PDU header.
Definition: PduHeader.cpp:16
virtual SerializeStatus serializeFrom(U8 val, Endianness mode=Endianness::BIG)=0
Serialize an 8-bit unsigned integer value.
Fw::SerializeStatus fromSerialBuffer(Fw::SerialBufferBase &serialBuffer)
Initialize this Header from a SerialBufferBase.
Definition: PduHeader.cpp:163
SerializeStatus
forward declaration for string
virtual SerializeStatus deserializeTo(U8 &val, Endianness mode=Endianness::BIG)=0
Deserialize an 8-bit unsigned integer value.
Fw::SerializeStatus serializeTo(Fw::SerialBufferBase &buffer, Fw::Endianness mode=Fw::Endianness::BIG) const override
Fw::Serializable interface - serialize to buffer.
Definition: MetadataPdu.cpp:61
U32 TransactionSeq
transaction sequence number size
Omit length from serialization.
Data was left in the buffer, but not enough to deserialize.
U32 getBufferSize() const override
Compute the buffer size needed.
Definition: MetadataPdu.cpp:44
U32 getBufferSize() const
Compute the buffer size needed to hold this Header.
Definition: PduHeader.cpp:80
Deserialized type ID didn&#39;t match.
const char * toChar() const
Convert to a C-style char*.
PduHeader m_header
The PDU header (common to all PDUs)
Definition: PduBase.hpp:27
Fw::SerializeStatus deserializeFrom(Fw::SerialBufferBase &buffer, Fw::Endianness mode=Fw::Endianness::BIG) override
Fw::Serializable interface - deserialize from buffer.
Definition: MetadataPdu.cpp:65
U32 FileSize
File size and offset type.
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:54
void setPduDataLength(U16 length)
Set PDU data length (used during encoding)
Definition: PduHeader.hpp:136
The type of a PDU header (common to all PDUs)
Definition: PduHeader.hpp:47
Fw::SerializeStatus toSerialBuffer(Fw::SerialBufferBase &serialBuffer) const
Write this Header to a SerialBufferBase.
Definition: PduHeader.cpp:95
RateGroupDivider component implementation.
virtual SizeType length() const
Get the length of the string.
void initialize(PduDirection direction, Cfdp::Class::T txmMode, EntityId sourceEid, TransactionSeq transactionSeq, EntityId destEid, FileSize fileSize, const Fw::String &sourceFilename, const Fw::String &destFilename, ChecksumType checksumType, U8 closureRequested)
Initialize a Metadata PDU.
Definition: MetadataPdu.cpp:16
Endianness
T
The raw enum type.
Definition: ClassEnumAc.hpp:42
#define FW_ASSERT(...)
Definition: Assert.hpp:14