GCC Code Coverage Report


Directory: ./
File: FileDataPdu.cpp
Date: 2026-09-03 22:13:23
Exec Total Coverage
Lines: 0 84 0.0%
Functions: 0 9 0.0%
Branches: 0 54 0.0%

Line Branch Exec Source
1 // ======================================================================
2 // \title FileDataPdu.cpp
3 // \author Brian Campuzano
4 // \brief cpp file for CFDP File Data PDU
5 // ======================================================================
6
7 #include <Fw/Types/Assert.hpp>
8 #include <Svc/Ccsds/CfdpManager/Types/FileDataPdu.hpp>
9 #include <config/CfdpCfg.hpp>
10
11 namespace Svc {
12 namespace Ccsds {
13 namespace Cfdp {
14
15 void FileDataPdu::initialize(PduDirection direction,
16 Cfdp::Class::T txmMode,
17 EntityId sourceEid,
18 TransactionSeq transactionSeq,
19 EntityId destEid,
20 FileSize offset,
21 U16 dataSize,
22 const U8* data) {
23 // Initialize header with PduTypeEnum::FILE_DATA type
24 this->m_header.initialize(PduTypeEnum::FILE_DATA, direction, txmMode, sourceEid, transactionSeq, destEid);
25
26 this->m_offset = offset;
27 this->m_dataSize = dataSize;
28 this->m_data = data;
29 }
30
31 U32 FileDataPdu::getBufferSize() const {
32 U32 size = this->m_header.getBufferSize();
33
34 // Offset field size depends on large file flag
35 if (this->m_header.m_largeFileFlag == LargeFileFlag::LARGE_FILE_64_BIT) {
36 size += static_cast<U32>(sizeof(U64)); // 8-byte offset
37 } else {
38 size += static_cast<U32>(sizeof(U32)); // 4-byte offset
39 }
40
41 size += this->m_dataSize; // actual data
42 return size;
43 }
44
45 U32 FileDataPdu::getMaxFileDataSize() {
46 U32 size = this->m_header.getBufferSize();
47
48 // Offset field size depends on large file flag
49 if (this->m_header.m_largeFileFlag == LargeFileFlag::LARGE_FILE_64_BIT) {
50 size += static_cast<U32>(sizeof(U64)); // 8-byte offset
51 } else {
52 size += static_cast<U32>(sizeof(U32)); // 4-byte offset
53 }
54
55 return MaxPduSize - size;
56 }
57
58 Fw::SerializeStatus FileDataPdu::toBuffer(Fw::Buffer& buffer) const {
59 Fw::SerialBuffer serialBuffer(buffer.getData(), buffer.getSize());
60 Fw::SerializeStatus status = this->toSerialBuffer(serialBuffer);
61 if (status == Fw::FW_SERIALIZE_OK) {
62 buffer.setSize(serialBuffer.getSize());
63 }
64 return status;
65 }
66
67 Fw::SerializeStatus FileDataPdu::fromBuffer(const Fw::Buffer& buffer) {
68 // Create SerialBuffer from Buffer
69 Fw::SerialBuffer serialBuffer(const_cast<Fw::Buffer&>(buffer).getData(), const_cast<Fw::Buffer&>(buffer).getSize());
70 serialBuffer.fill();
71
72 // Deserialize header first
73 Fw::SerializeStatus status = this->m_header.fromSerialBuffer(serialBuffer);
74 if (status != Fw::FW_SERIALIZE_OK) {
75 return status;
76 }
77
78 // Validate this is a file data PDU
79 if (this->m_header.m_pduType != PduType::PDU_TYPE_FILE_DATA) {
80 return Fw::FW_DESERIALIZE_TYPE_MISMATCH;
81 }
82
83 // Set the type to PduTypeEnum::FILE_DATA since we've validated it
84 this->m_header.m_type = PduTypeEnum::FILE_DATA;
85
86 // Deserialize the file data body
87 return this->fromSerialBuffer(serialBuffer);
88 }
89
90 Fw::SerializeStatus FileDataPdu::toSerialBuffer(Fw::SerialBuffer& serialBuffer) const {
91 FW_ASSERT(this->m_header.m_type == PduTypeEnum::FILE_DATA);
92
93 // Calculate PDU data length (everything after header)
94 U32 dataLength = this->getBufferSize() - this->m_header.getBufferSize();
95
96 // Update header with data length
97 PduHeader headerCopy = this->m_header;
98 headerCopy.setPduDataLength(static_cast<U16>(dataLength));
99
100 // Serialize header
101 Fw::SerializeStatus status = headerCopy.toSerialBuffer(serialBuffer);
102 if (status != Fw::FW_SERIALIZE_OK) {
103 return status;
104 }
105
106 // Serialize offset - size depends on large file flag
107 if (this->m_header.m_largeFileFlag == LargeFileFlag::LARGE_FILE_64_BIT) {
108 // Serialize as 8 bytes (64-bit)
109 U64 offset64 = this->m_offset;
110 status = serialBuffer.serializeFrom(offset64);
111 } else {
112 // Serialize as 4 bytes (32-bit)
113 U32 offset32 = static_cast<U32>(this->m_offset);
114 status = serialBuffer.serializeFrom(offset32);
115 }
116 if (status != Fw::FW_SERIALIZE_OK) {
117 return status;
118 }
119
120 // Serialize file data (only if there is data to serialize)
121 if (this->m_dataSize > 0) {
122 status = serialBuffer.pushBytes(this->m_data, this->m_dataSize);
123 if (status != Fw::FW_SERIALIZE_OK) {
124 return status;
125 }
126 }
127
128 return Fw::FW_SERIALIZE_OK;
129 }
130
131 Fw::SerializeStatus FileDataPdu::fromSerialBuffer(Fw::SerialBuffer& serialBuffer) {
132 FW_ASSERT(this->m_header.m_type == PduTypeEnum::FILE_DATA);
133
134 // Deserialize offset - size depends on large file flag
135 Fw::SerializeStatus status;
136 U8 offsetSize;
137 status = serialBuffer.deserializeTo(this->m_offset);
138 if (status != Fw::FW_SERIALIZE_OK) {
139 return status;
140 }
141 offsetSize = sizeof(this->m_offset);
142
143 // Calculate remaining data size based on header's PDU data length
144 U16 pduDataLength = this->m_header.getPduDataLength();
145
146 // Defensive check: prevent unsigned integer underflow
147 if (pduDataLength < offsetSize) {
148 return Fw::FW_DESERIALIZE_SIZE_MISMATCH;
149 }
150
151 this->m_dataSize = static_cast<U16>(pduDataLength - offsetSize); // minus offset size
152
153 // Point to the data in the buffer (zero-copy)
154 this->m_data = serialBuffer.getBuffAddrLeft();
155
156 // Validate we have enough bytes
157 if (serialBuffer.getDeserializeSizeLeft() < this->m_dataSize) {
158 return Fw::FW_DESERIALIZE_SIZE_MISMATCH;
159 }
160
161 // Advance the buffer pointer
162 U8 tempBuf[1]; // Dummy buffer for validation
163 for (U16 i = 0; i < this->m_dataSize; ++i) {
164 status = serialBuffer.popBytes(tempBuf, 1);
165 if (status != Fw::FW_SERIALIZE_OK) {
166 return status;
167 }
168 }
169
170 return Fw::FW_SERIALIZE_OK;
171 }
172
173 Fw::SerializeStatus FileDataPdu::serializeTo(Fw::SerialBufferBase& buffer, Fw::Endianness mode) const {
174 // Caller contract guarantees a SerialBuffer.
175 Fw::SerialBuffer* serialBuffer = static_cast<Fw::SerialBuffer*>(&buffer);
176 return this->toSerialBuffer(*serialBuffer);
177 }
178
179 Fw::SerializeStatus FileDataPdu::deserializeFrom(Fw::SerialBufferBase& buffer, Fw::Endianness mode) {
180 // Caller contract guarantees a SerialBuffer.
181 Fw::SerialBuffer* serialBuffer = static_cast<Fw::SerialBuffer*>(&buffer);
182
183 // Deserialize header first
184 Fw::SerializeStatus status = this->m_header.fromSerialBuffer(*serialBuffer);
185 if (status != Fw::FW_SERIALIZE_OK) {
186 return status;
187 }
188
189 // Deserialize the file data body
190 return this->fromSerialBuffer(*serialBuffer);
191 }
192
193 } // namespace Cfdp
194 } // namespace Ccsds
195 } // namespace Svc
196