fsfw/src/fsfw/cfdp/pdu/FinishedPduDeserializer.cpp

89 lines
3.4 KiB
C++
Raw Normal View History

#include "FinishedPduDeserializer.h"
2022-02-02 10:29:30 +01:00
FinishPduDeserializer::FinishPduDeserializer(const uint8_t* pduBuf, size_t maxSize,
FinishedInfo& info)
2022-08-03 16:00:48 +02:00
: FileDirectiveReader(pduBuf, maxSize), finishedInfo(info) {}
ReturnValue_t FinishPduDeserializer::parseData() {
2022-08-03 16:00:48 +02:00
ReturnValue_t result = FileDirectiveReader::parseData();
2022-08-16 01:08:26 +02:00
if (result != returnvalue::OK) {
return result;
2022-02-02 10:29:30 +01:00
}
2022-08-03 16:00:48 +02:00
size_t currentIdx = FileDirectiveReader::getHeaderSize();
2022-08-08 18:29:32 +02:00
const uint8_t* buf = pointers.rawPtr + currentIdx;
2022-08-03 16:00:48 +02:00
size_t remSize = FileDirectiveReader::getWholePduSize() - currentIdx;
2022-02-02 10:29:30 +01:00
if (remSize < 1) {
return SerializeIF::STREAM_TOO_SHORT;
}
uint8_t firstByte = *buf;
2022-08-03 16:00:48 +02:00
auto condCode = static_cast<cfdp::ConditionCode>((firstByte >> 4) & 0x0f);
2022-02-02 10:29:30 +01:00
finishedInfo.setConditionCode(condCode);
2022-08-09 21:03:56 +02:00
finishedInfo.setDeliveryCode(static_cast<cfdp::FileDeliveryCode>(firstByte >> 2 & 0b1));
finishedInfo.setFileStatus(static_cast<cfdp::FileDeliveryStatus>(firstByte & 0b11));
2022-02-02 10:29:30 +01:00
buf += 1;
remSize -= 1;
currentIdx += 1;
if (remSize > 0) {
result = parseTlvs(remSize, currentIdx, buf, condCode);
}
return result;
}
2022-02-02 10:29:30 +01:00
FinishedInfo& FinishPduDeserializer::getInfo() { return finishedInfo; }
2022-02-02 10:29:30 +01:00
ReturnValue_t FinishPduDeserializer::parseTlvs(size_t remLen, size_t currentIdx, const uint8_t* buf,
cfdp::ConditionCode conditionCode) {
2022-08-16 01:08:26 +02:00
ReturnValue_t result = returnvalue::OK;
2022-02-02 10:29:30 +01:00
size_t fsResponsesIdx = 0;
auto endianness = getEndianness();
FilestoreResponseTlv** fsResponseArray = nullptr;
size_t fsResponseMaxArrayLen = 0;
EntityIdTlv* faultLocation = nullptr;
cfdp::TlvTypes nextTlv = cfdp::TlvTypes::INVALID_TLV;
while (remLen > 0) {
// Simply forward parse the TLV type. Every TLV type except the last one must be a Filestore
// Response TLV, and even the last one can be a Filestore Response TLV if the fault
// location is omitted
if (currentIdx + 2 > maxSize) {
return SerializeIF::STREAM_TOO_SHORT;
}
nextTlv = static_cast<cfdp::TlvTypes>(*buf);
if (nextTlv == cfdp::TlvTypes::FILESTORE_RESPONSE) {
if (fsResponseArray == nullptr) {
if (not finishedInfo.canHoldFsResponses()) {
return cfdp::FINISHED_CANT_PARSE_FS_RESPONSES;
}
2022-02-02 10:29:30 +01:00
result =
finishedInfo.getFilestoreResonses(&fsResponseArray, nullptr, &fsResponseMaxArrayLen);
}
if (fsResponsesIdx == fsResponseMaxArrayLen) {
return cfdp::FINISHED_CANT_PARSE_FS_RESPONSES;
}
result = fsResponseArray[fsResponsesIdx]->deSerialize(&buf, &remLen, endianness);
2022-08-16 01:08:26 +02:00
if (result != returnvalue::OK) {
2022-02-02 10:29:30 +01:00
return result;
}
fsResponsesIdx += 1;
} else if (nextTlv == cfdp::TlvTypes::ENTITY_ID) {
// This needs to be the last TLV and it should not be here if the condition code
// is "No Error" or "Unsupported Checksum Type"
if (conditionCode == cfdp::ConditionCode::NO_ERROR or
conditionCode == cfdp::ConditionCode::UNSUPPORTED_CHECKSUM_TYPE) {
return cfdp::INVALID_TLV_TYPE;
}
result = finishedInfo.getFaultLocation(&faultLocation);
2022-08-16 01:08:26 +02:00
if (result != returnvalue::OK) {
2022-02-02 10:29:30 +01:00
return result;
}
result = faultLocation->deSerialize(&buf, &remLen, endianness);
2022-08-16 01:08:26 +02:00
if (result != returnvalue::OK) {
2022-02-02 10:29:30 +01:00
return result;
}
} else {
return cfdp::INVALID_TLV_TYPE;
}
2022-02-02 10:29:30 +01:00
}
finishedInfo.setFilestoreResponsesArrayLen(fsResponsesIdx);
return result;
}