fsfw/src/fsfw/cfdp/tlv/FilestoreResponseTlv.cpp

125 lines
4.3 KiB
C++

#include "FilestoreResponseTlv.h"
FilestoreResponseTlv::FilestoreResponseTlv(cfdp::FilestoreActionCode actionCode, uint8_t statusCode,
cfdp::Lv& firstFileName, cfdp::Lv* fsMsg): FilestoreTlvBase(actionCode, firstFileName),
statusCode(statusCode), filestoreMsg(fsMsg) {
}
FilestoreResponseTlv::FilestoreResponseTlv(cfdp::Lv &firstFileName, cfdp::Lv* fsMsg):
FilestoreTlvBase(firstFileName), statusCode(0), filestoreMsg(fsMsg) {
}
uint8_t FilestoreResponseTlv::getLengthField() const {
size_t optFieldsLen = 0;
if(secondFileName != nullptr) {
optFieldsLen += secondFileName->getSerializedSize();
}
if(filestoreMsg != nullptr) {
optFieldsLen += filestoreMsg->getSerializedSize();
} else {
optFieldsLen += 1;
}
return 1 + firstFileName.getSerializedSize() + optFieldsLen;
}
void FilestoreResponseTlv::setSecondFileName(cfdp::Lv *secondFileName) {
this->secondFileName = secondFileName;
}
void FilestoreResponseTlv::setFilestoreMessage(cfdp::Lv *filestoreMsg) {
this->filestoreMsg = filestoreMsg;
}
ReturnValue_t FilestoreResponseTlv::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const {
ReturnValue_t result = commonSerialize(buffer, size, maxSize, streamEndianness,
true, this->statusCode);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = firstFileName.serialize(buffer, size, maxSize, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if(requiresSecondFileName()) {
if(secondFileName == nullptr) {
secondFileNameMissing();
return cfdp::FILESTORE_REQUIRES_SECOND_FILE;
}
}
if(filestoreMsg != nullptr) {
result = filestoreMsg->serialize(buffer, size, maxSize, streamEndianness);
}
else {
if(*size == maxSize) {
return SerializeIF::BUFFER_TOO_SHORT;
}
**buffer = 0;
*buffer += 1;
*size +=1;
}
return result;
}
ReturnValue_t FilestoreResponseTlv::deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) {
ReturnValue_t result = commonDeserialize(buffer, size, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return deSerializeFromValue(buffer, size, streamEndianness);
}
ReturnValue_t FilestoreResponseTlv::deSerializeFromValue(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) {
// The common function above checks whether at least one byte is remaining
this->actionCode = static_cast<cfdp::FilestoreActionCode>((**buffer >> 4) & 0x0f);
this->statusCode = **buffer & 0x0f;
*buffer += 1;
*size -= 1;
ReturnValue_t result = firstFileName.deSerialize(buffer, size, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if(requiresSecondFileName()) {
if(secondFileName == nullptr) {
return cfdp::FILESTORE_REQUIRES_SECOND_FILE;
}
result = secondFileName->deSerialize(buffer, size, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
}
// If the filestore message is not empty, the deserialization is only considered successfully
// if the filestore message can be parsed. Also, if data follows after the FS response,
// the FS msg needs to be set as well.
if(*size == 0 or (*size > 1 and filestoreMsg == nullptr)) {
// Filestore message missing or can't parse it
return cfdp::FILESTORE_RESPONSE_CANT_PARSE_FS_MESSAGE;
}
if(filestoreMsg == nullptr) {
*size -= 1;
*buffer += 1;
// Ignore empty filestore message
return HasReturnvaluesIF::RETURN_OK;
}
return filestoreMsg->deSerialize(buffer, size, streamEndianness);
}
ReturnValue_t FilestoreResponseTlv::deSerialize(const cfdp::Tlv &tlv, Endianness endianness) {
const uint8_t* ptr = tlv.getValue();
size_t remSz = tlv.getSerializedSize();
return deSerializeFromValue(&ptr, &remSz, endianness);
}
uint8_t FilestoreResponseTlv::getStatusCode() const {
return statusCode;
}
cfdp::TlvTypes FilestoreResponseTlv::getType() const {
return cfdp::TlvTypes::FILESTORE_RESPONSE;
}