F´ Flight Software - C/C++ Documentation
A framework for building embedded system applications to NASA flight quality standards.
Tlv.cpp
Go to the documentation of this file.
1 // ======================================================================
2 // \title Tlv.cpp
3 // \author Brian Campuzano
4 // \brief cpp file for CFDP TLV (Type-Length-Value) classes
5 // ======================================================================
6 
7 #include <Fw/Types/Assert.hpp>
9 #include <cstring>
10 
11 namespace Svc {
12 namespace Ccsds {
13 namespace Cfdp {
14 
15 // ======================================================================
16 // TlvData
17 // ======================================================================
18 
19 TlvData::TlvData() : m_dataLength(0) {
20  // Initialize union to zero
21  memset(this->m_rawData, 0, sizeof(this->m_rawData));
22 }
23 
25  this->m_eid = eid;
26  // Entity ID length depends on the value
27  // For now, use sizeof(EntityId) as the length
28  this->m_dataLength = sizeof(EntityId);
29 }
30 
31 void TlvData::setData(const U8* data, U8 length) {
32  // length is U8 so it's always <= 255, assertion is redundant
33  FW_ASSERT(data != nullptr);
34 
35  memcpy(this->m_rawData, data, length);
36  this->m_dataLength = length;
37 }
38 
40  return this->m_eid;
41 }
42 
43 const U8* TlvData::getData() const {
44  return this->m_rawData;
45 }
46 
48  return this->m_dataLength;
49 }
50 
51 // ======================================================================
52 // Tlv
53 // ======================================================================
54 
56  // Default constructor
57 }
58 
60  this->m_type = TlvType::TLV_TYPE_ENTITY_ID;
61  this->m_data.setEntityId(eid);
62 }
63 
64 void Tlv::initialize(TlvType type, const U8* data, U8 length) {
65  this->m_type = type;
66  this->m_data.setData(data, length);
67 }
68 
70  return this->m_type;
71 }
72 
73 const TlvData& Tlv::getData() const {
74  return this->m_data;
75 }
76 
77 U32 Tlv::getEncodedSize() const {
78  // Type (1 byte) + Length (1 byte) + Data (variable)
79  return 2 + this->m_data.getLength();
80 }
81 
83  Fw::SerializeStatus status;
84 
85  // Serialize type byte
86  status = serialBuffer.serializeFrom(static_cast<U8>(this->m_type));
87  if (status != Fw::FW_SERIALIZE_OK) {
88  return status;
89  }
90 
91  // Serialize length byte
92  U8 length = this->m_data.getLength();
93  status = serialBuffer.serializeFrom(length);
94  if (status != Fw::FW_SERIALIZE_OK) {
95  return status;
96  }
97 
98  // Serialize data
99  if (this->m_type == TlvType::TLV_TYPE_ENTITY_ID) {
100  // For Entity ID, serialize as EntityId
101  EntityId eid = this->m_data.getEntityId();
102  status = serialBuffer.serializeFrom(eid);
103  if (status != Fw::FW_SERIALIZE_OK) {
104  return status;
105  }
106  } else {
107  // For other types, serialize raw data
108  const U8* data = this->m_data.getData();
109  for (U8 i = 0; i < length; i++) {
110  status = serialBuffer.serializeFrom(data[i]);
111  if (status != Fw::FW_SERIALIZE_OK) {
112  return status;
113  }
114  }
115  }
116 
117  return Fw::FW_SERIALIZE_OK;
118 }
119 
121  Fw::SerializeStatus status;
122 
123  // Deserialize type byte
124  U8 typeVal;
125  status = serialBuffer.deserializeTo(typeVal);
126  if (status != Fw::FW_SERIALIZE_OK) {
127  return status;
128  }
129  this->m_type = static_cast<TlvType>(typeVal);
130 
131  // Deserialize length byte
132  U8 length;
133  status = serialBuffer.deserializeTo(length);
134  if (status != Fw::FW_SERIALIZE_OK) {
135  return status;
136  }
137 
138  // Deserialize data
139  if (this->m_type == TlvType::TLV_TYPE_ENTITY_ID) {
140  // For Entity ID, read length bytes and convert to EntityId
141  // Per CFDP spec, Entity IDs can be 1, 2, 4, or 8 bytes
142  // We support up to sizeof(EntityId) bytes
143  if (length > sizeof(EntityId)) {
145  }
146 
147  // Read length bytes as raw data, then convert to EntityId (big-endian)
148  U8 rawData[sizeof(EntityId)];
149  memset(rawData, 0, sizeof(rawData)); // Zero-pad
150 
151  for (U8 i = 0; i < length; i++) {
152  status = serialBuffer.deserializeTo(rawData[i]);
153  if (status != Fw::FW_SERIALIZE_OK) {
154  return status;
155  }
156  }
157 
158  // Convert big-endian bytes to EntityId
159  EntityId eid = 0;
160  for (U8 i = 0; i < length; i++) {
161  eid = (eid << 8) | rawData[i];
162  }
163 
164  this->m_data.setEntityId(eid);
165  } else {
166  // For other types, deserialize raw data
167  U8 rawData[256];
168  for (U8 i = 0; i < length; i++) {
169  status = serialBuffer.deserializeTo(rawData[i]);
170  if (status != Fw::FW_SERIALIZE_OK) {
171  return status;
172  }
173  }
174  this->m_data.setData(rawData, length);
175  }
176 
177  return Fw::FW_SERIALIZE_OK;
178 }
179 
180 // ======================================================================
181 // TlvList
182 // ======================================================================
183 
184 TlvList::TlvList() : m_numTlv(0) {
185  // Default constructor
186 }
187 
188 bool TlvList::appendTlv(const Tlv& tlv) {
189  if (this->m_numTlv >= MaxTlv) {
190  return false; // List is full
191  }
192 
193  this->m_tlvs[this->m_numTlv] = tlv;
194  this->m_numTlv++;
195  return true;
196 }
197 
199  this->m_numTlv = 0;
200 }
201 
203  return this->m_numTlv;
204 }
205 
206 const Tlv& TlvList::getTlv(U8 index) const {
207  FW_ASSERT(index < this->m_numTlv, index, this->m_numTlv);
208  return this->m_tlvs[index];
209 }
210 
212  U32 size = 0;
213  for (U8 i = 0; i < this->m_numTlv; i++) {
214  size += this->m_tlvs[i].getEncodedSize();
215  }
216  return size;
217 }
218 
220  Fw::SerializeStatus status;
221 
222  // Encode all TLVs
223  for (U8 i = 0; i < this->m_numTlv; i++) {
224  status = this->m_tlvs[i].toSerialBuffer(serialBuffer);
225  if (status != Fw::FW_SERIALIZE_OK) {
226  return status;
227  }
228  }
229 
230  return Fw::FW_SERIALIZE_OK;
231 }
232 
234  Fw::SerializeStatus status;
235 
236  // Clear existing TLVs
237  this->m_numTlv = 0;
238 
239  // Decode TLVs until buffer is exhausted or max count reached
240  while (serialBuffer.getDeserializeSizeLeft() > 0 && this->m_numTlv < MaxTlv) {
241  status = this->m_tlvs[this->m_numTlv].fromSerialBuffer(serialBuffer);
242  if (status != Fw::FW_SERIALIZE_OK) {
243  // If we fail to decode a TLV, stop (could be end of buffer or invalid data)
244  // Only return error if we haven't successfully decoded any TLVs yet
245  if (this->m_numTlv == 0) {
246  return status;
247  } else {
248  // We've decoded some TLVs successfully, so consider this a success
249  break;
250  }
251  }
252  this->m_numTlv++;
253  }
254 
255  return Fw::FW_SERIALIZE_OK;
256 }
257 
258 } // namespace Cfdp
259 } // namespace Ccsds
260 } // namespace Svc
Serialization/Deserialization operation was successful.
bool appendTlv(const Tlv &tlv)
Definition: Tlv.cpp:188
const TlvData & getData() const
Definition: Tlv.cpp:73
U32 EntityId
Entity id size.
Fw::SerializeStatus toSerialBuffer(Fw::SerialBufferBase &serialBuffer) const
Definition: Tlv.cpp:219
TlvType getType() const
Definition: Tlv.cpp:69
const Tlv & getTlv(U8 index) const
Definition: Tlv.cpp:206
Deserialization data had incorrect values (unexpected data types)
virtual SerializeStatus serializeFrom(U8 val, Endianness mode=Endianness::BIG)=0
Serialize an 8-bit unsigned integer value.
SerializeStatus
forward declaration for string
virtual SerializeStatus deserializeTo(U8 &val, Endianness mode=Endianness::BIG)=0
Deserialize an 8-bit unsigned integer value.
U32 getEncodedSize() const
Definition: Tlv.cpp:77
Fw::SerializeStatus fromSerialBuffer(Fw::SerialBufferBase &serialBuffer)
Definition: Tlv.cpp:120
U8 getLength() const
Definition: Tlv.cpp:47
U8 getNumTlv() const
Definition: Tlv.cpp:202
Fw::SerializeStatus fromSerialBuffer(Fw::SerialBufferBase &serialBuffer)
Definition: Tlv.cpp:233
void setEntityId(EntityId eid)
Definition: Tlv.cpp:24
Single TLV entry.
Definition: Tlv.hpp:59
const U8 * getData() const
Definition: Tlv.cpp:43
TLV data storage.
Definition: Tlv.hpp:31
virtual Serializable::SizeType getDeserializeSizeLeft() const =0
Get remaining deserialization buffer size.
void setData(const U8 *data, U8 length)
Definition: Tlv.cpp:31
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:54
EntityId getEntityId() const
Definition: Tlv.cpp:39
Fw::SerializeStatus toSerialBuffer(Fw::SerialBufferBase &serialBuffer) const
Definition: Tlv.cpp:82
RateGroupDivider component implementation.
U32 getEncodedSize() const
Definition: Tlv.cpp:211
#define FW_ASSERT(...)
Definition: Assert.hpp:14
void initialize(EntityId eid)
Definition: Tlv.cpp:59