Compare commits
25 Commits
60dcacf432
...
move-pus-t
Author | SHA1 | Date | |
---|---|---|---|
dfe7c378da
|
|||
cc3e64e70d | |||
6021257a87
|
|||
63c238005e | |||
0f604b35c6 | |||
e3a815444e | |||
19093866ee | |||
497f947237
|
|||
5bd020193b
|
|||
420c0625a5
|
|||
42a0b15303
|
|||
c199cbedaa
|
|||
c4e18cc2f3
|
|||
c143198494
|
|||
448fbd0d38
|
|||
470f589bde
|
|||
dfcfb035be
|
|||
6e53582dc9
|
|||
fb1500e041
|
|||
ea2e58249d
|
|||
9ef63825f3
|
|||
073cb4b3d5
|
|||
8c11685240
|
|||
cb1aaea6cd
|
|||
22df8f6147
|
@@ -17,7 +17,7 @@ static constexpr char CFDP_VERSION_2_NAME[] = "CCSDS 727.0-B-5";
|
||||
static constexpr uint8_t CFDP_VERSION_2 = 0b001;
|
||||
static constexpr uint8_t VERSION_BITS = CFDP_VERSION_2 << 5;
|
||||
|
||||
static constexpr uint8_t CFDP_CLASS_ID = CLASS_ID::CFDP;
|
||||
static constexpr uint8_t CFDP_CLASS_ID = CLASS_ID::CFDP_BASE;
|
||||
|
||||
static constexpr ReturnValue_t INVALID_TLV_TYPE = returnvalue::makeCode(CFDP_CLASS_ID, 1);
|
||||
static constexpr ReturnValue_t INVALID_DIRECTIVE_FIELD = returnvalue::makeCode(CFDP_CLASS_ID, 2);
|
||||
|
@@ -146,7 +146,7 @@ ReturnValue_t cfdp::DestHandler::handleMetadataPdu(const PacketInfo& info) {
|
||||
return handleMetadataParseError(result, constAccessorPair.second.data(),
|
||||
constAccessorPair.second.size());
|
||||
}
|
||||
return startTransaction(reader, metadataInfo);
|
||||
return startTransaction(reader);
|
||||
}
|
||||
|
||||
ReturnValue_t cfdp::DestHandler::handleFileDataPdu(const cfdp::PacketInfo& info) {
|
||||
@@ -274,8 +274,7 @@ ReturnValue_t cfdp::DestHandler::handleMetadataParseError(ReturnValue_t result,
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
ReturnValue_t cfdp::DestHandler::startTransaction(MetadataPduReader& reader,
|
||||
MetadataGenericInfo& info) {
|
||||
ReturnValue_t cfdp::DestHandler::startTransaction(const MetadataPduReader& reader) {
|
||||
if (fsmRes.state != CfdpState::IDLE) {
|
||||
// According to standard, discard metadata PDU if we are busy
|
||||
return OK;
|
||||
@@ -283,25 +282,31 @@ ReturnValue_t cfdp::DestHandler::startTransaction(MetadataPduReader& reader,
|
||||
ReturnValue_t result = OK;
|
||||
size_t sourceNameSize = 0;
|
||||
|
||||
const uint8_t* sourceNamePtr = reader.getSourceFileName().getValue(&sourceNameSize);
|
||||
if (sourceNameSize + 1 > transactionParams.sourceName.size()) {
|
||||
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "source filename too large");
|
||||
return FAILED;
|
||||
if (not reader.getSourceFileName().isEmpty()) {
|
||||
const uint8_t* sourceNamePtr = reader.getSourceFileName().getValue(&sourceNameSize);
|
||||
if (sourceNameSize + 1 > transactionParams.sourceName.size()) {
|
||||
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "source filename too large");
|
||||
return FAILED;
|
||||
}
|
||||
std::memcpy(transactionParams.sourceName.data(), sourceNamePtr, sourceNameSize);
|
||||
transactionParams.sourceName[sourceNameSize] = '\0';
|
||||
}
|
||||
std::memcpy(transactionParams.sourceName.data(), sourceNamePtr, sourceNameSize);
|
||||
transactionParams.sourceName[sourceNameSize] = '\0';
|
||||
size_t destNameSize = 0;
|
||||
const uint8_t* destNamePtr = reader.getDestFileName().getValue(&destNameSize);
|
||||
if (destNameSize + 1 > transactionParams.destName.size()) {
|
||||
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "dest filename too large");
|
||||
return FAILED;
|
||||
if (not reader.getDestFileName().isEmpty()) {
|
||||
const uint8_t* destNamePtr = reader.getDestFileName().getValue(&destNameSize);
|
||||
if (destNameSize + 1 > transactionParams.destName.size()) {
|
||||
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "dest filename too large");
|
||||
return FAILED;
|
||||
}
|
||||
std::memcpy(transactionParams.destName.data(), destNamePtr, destNameSize);
|
||||
transactionParams.destName[destNameSize] = '\0';
|
||||
}
|
||||
std::memcpy(transactionParams.destName.data(), destNamePtr, destNameSize);
|
||||
transactionParams.destName[destNameSize] = '\0';
|
||||
|
||||
transactionParams.metadataOnly = true;
|
||||
// If both dest name size and source name size are 0, we are dealing with a metadata only PDU,
|
||||
// so there is no need to create a file or truncate an existing file
|
||||
if (destNameSize > 0 and sourceNameSize > 0) {
|
||||
transactionParams.metadataOnly = false;
|
||||
FilesystemParams fparams(transactionParams.destName.data());
|
||||
// handling to allow only specifying target directory. Example:
|
||||
// Source path /test/hello.txt, dest path /tmp -> dest path /tmp/hello.txt
|
||||
@@ -338,12 +343,19 @@ ReturnValue_t cfdp::DestHandler::startTransaction(MetadataPduReader& reader,
|
||||
#endif
|
||||
return FAILED;
|
||||
}
|
||||
fsmRes.step = TransactionStep::TRANSACTION_START;
|
||||
if (reader.getTransmissionMode() == TransmissionMode::UNACKNOWLEDGED) {
|
||||
fsmRes.state = CfdpState::BUSY_CLASS_1_NACKED;
|
||||
} else if (reader.getTransmissionMode() == TransmissionMode::ACKNOWLEDGED) {
|
||||
fsmRes.state = CfdpState::BUSY_CLASS_2_ACKED;
|
||||
}
|
||||
if (transactionParams.metadataOnly) {
|
||||
fsmRes.step = TransactionStep::TRANSFER_COMPLETION;
|
||||
} else {
|
||||
// Kind of ugly, make FSM working on packet per packet basis..
|
||||
fsmRes.step = TransactionStep::TRANSACTION_START;
|
||||
fsmRes.step = TransactionStep::RECEIVING_FILE_DATA_PDUS;
|
||||
}
|
||||
auto& info = reader.getGenericInfo();
|
||||
transactionParams.checksumType = info.getChecksumType();
|
||||
transactionParams.closureRequested = info.isClosureRequested();
|
||||
reader.fillConfig(transactionParams.pduConf);
|
||||
@@ -351,20 +363,19 @@ ReturnValue_t cfdp::DestHandler::startTransaction(MetadataPduReader& reader,
|
||||
transactionParams.transactionId.entityId = transactionParams.pduConf.sourceId;
|
||||
transactionParams.transactionId.seqNum = transactionParams.pduConf.seqNum;
|
||||
transactionParams.fileSize = info.getFileSize();
|
||||
fsmRes.step = TransactionStep::RECEIVING_FILE_DATA_PDUS;
|
||||
MetadataRecvdParams params(transactionParams.transactionId, transactionParams.pduConf.sourceId,
|
||||
transactionParams.fileSize);
|
||||
params.destFileName = transactionParams.destName.data();
|
||||
params.sourceFileName = transactionParams.sourceName.data();
|
||||
unsigned tlvIdx = 0;
|
||||
params.numberOfMsgsToUser = 0;
|
||||
for (const auto& opt : tlvVec) {
|
||||
if (opt.getType() == TlvType::MSG_TO_USER) {
|
||||
msgToUserVec[tlvIdx] = MessageToUserTlv(opt.getValue(), opt.getLengthField());
|
||||
tlvIdx++;
|
||||
msgToUserVec[params.numberOfMsgsToUser] =
|
||||
MessageToUserTlv(opt.getValue(), opt.getLengthField());
|
||||
params.numberOfMsgsToUser++;
|
||||
}
|
||||
}
|
||||
params.msgsToUserArray = msgToUserVec.data();
|
||||
params.msgsToUserLen = tlvIdx;
|
||||
destParams.user.metadataRecvdIndication(params);
|
||||
return result;
|
||||
}
|
||||
|
@@ -125,11 +125,13 @@ class DestHandler {
|
||||
crc = 0;
|
||||
progress = 0;
|
||||
remoteCfg = nullptr;
|
||||
metadataOnly = false;
|
||||
closureRequested = false;
|
||||
vfsErrorCount = 0;
|
||||
checksumType = ChecksumType::NULL_CHECKSUM;
|
||||
}
|
||||
|
||||
bool metadataOnly = false;
|
||||
ChecksumType checksumType = ChecksumType::NULL_CHECKSUM;
|
||||
bool closureRequested = false;
|
||||
uint16_t vfsErrorCount = 0;
|
||||
@@ -153,7 +155,7 @@ class DestHandler {
|
||||
cfdp::FsfwParams fsfwParams;
|
||||
FsmResult fsmRes;
|
||||
|
||||
ReturnValue_t startTransaction(MetadataPduReader& reader, MetadataGenericInfo& info);
|
||||
ReturnValue_t startTransaction(const MetadataPduReader& reader);
|
||||
ReturnValue_t handleMetadataPdu(const PacketInfo& info);
|
||||
ReturnValue_t handleFileDataPdu(const PacketInfo& info);
|
||||
ReturnValue_t handleEofPdu(const PacketInfo& info);
|
||||
|
@@ -16,7 +16,7 @@ class RemoteConfigTableIF {
|
||||
*/
|
||||
class OneRemoteConfigProvider : public RemoteConfigTableIF {
|
||||
public:
|
||||
explicit OneRemoteConfigProvider(RemoteEntityCfg cfg) : cfg(std::move(cfg)) {}
|
||||
explicit OneRemoteConfigProvider(RemoteEntityCfg& cfg) : cfg(cfg) {}
|
||||
|
||||
bool getRemoteCfg(const EntityId& remoteId, cfdp::RemoteEntityCfg** cfg_) override {
|
||||
if (remoteId != cfg.remoteId) {
|
||||
@@ -27,7 +27,7 @@ class OneRemoteConfigProvider : public RemoteConfigTableIF {
|
||||
}
|
||||
|
||||
private:
|
||||
RemoteEntityCfg cfg;
|
||||
RemoteEntityCfg& cfg;
|
||||
};
|
||||
|
||||
} // namespace cfdp
|
||||
|
@@ -13,27 +13,24 @@ cfdp::ReservedMessageParser::ReservedMessageParser(StorageManagerIF& ipcStore,
|
||||
MessageQueueId_t userDestination)
|
||||
: msgQueue(msgQueue), ipcStore(ipcStore), userDestination(userDestination) {}
|
||||
|
||||
ReturnValue_t cfdp::ReservedMessageParser::parse(const uint8_t* msgsToUserPtr,
|
||||
size_t sizeOfMessages) {
|
||||
ReturnValue_t result;
|
||||
size_t currentIdx = 0;
|
||||
const uint8_t* currentPtr = msgsToUserPtr;
|
||||
MessageToUserTlv tlv;
|
||||
size_t deserSize = sizeOfMessages;
|
||||
ReturnValue_t cfdp::ReservedMessageParser::parse(const MessageToUserTlv* msgsToUserArray,
|
||||
size_t numMsgToUser) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
cfdp::StringLv sourceFileName;
|
||||
cfdp::StringLv destFileName;
|
||||
PutRequest putRequest;
|
||||
const uint8_t* currentPtr = nullptr;
|
||||
size_t deserSize = 0;
|
||||
bool needToSendPutRequest = false;
|
||||
while (currentIdx < sizeOfMessages) {
|
||||
result = tlv.deSerialize(¤tPtr, &deserSize, SerializeIF::Endianness::NETWORK);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
for (size_t idx = 0; idx < numMsgToUser; idx++) {
|
||||
if (&msgsToUserArray[idx] == nullptr) {
|
||||
continue;
|
||||
}
|
||||
uint8_t messageType = 0;
|
||||
if (tlv.isReservedCfdpMessage(messageType, ¤tPtr, deserSize)) {
|
||||
if (msgsToUserArray[idx].isReservedCfdpMessage(messageType, ¤tPtr, deserSize)) {
|
||||
if (messageType == static_cast<uint8_t>(ProxyOpMessageType::PUT_REQUEST)) {
|
||||
EntityId entityIdLv;
|
||||
entityIdLv.deSerializeFromLv(¤tPtr, &deserSize);
|
||||
result = entityIdLv.deSerializeFromLv(¤tPtr, &deserSize);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -52,7 +49,6 @@ ReturnValue_t cfdp::ReservedMessageParser::parse(const uint8_t* msgsToUserPtr,
|
||||
needToSendPutRequest = true;
|
||||
}
|
||||
}
|
||||
currentIdx += tlv.getSerializedSize();
|
||||
}
|
||||
if (needToSendPutRequest) {
|
||||
store_address_t storeId;
|
||||
|
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "fsfw/cfdp/tlv/MessageToUserTlv.h"
|
||||
#include "fsfw/ipc/MessageQueueIF.h"
|
||||
#include "fsfw/storagemanager/StorageManagerIF.h"
|
||||
|
||||
@@ -15,7 +16,7 @@ class ReservedMessageParser {
|
||||
ReservedMessageParser(StorageManagerIF& ipcStore, MessageQueueIF& msgQueue,
|
||||
MessageQueueId_t userDestination);
|
||||
|
||||
ReturnValue_t parse(const uint8_t* msgsToUserPtr, size_t sizeOfMessages);
|
||||
ReturnValue_t parse(const MessageToUserTlv* msgsToUserArray, size_t numMsgsToUser);
|
||||
|
||||
private:
|
||||
MessageQueueIF& msgQueue;
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#include "fsfw/globalfunctions/arrayprinter.h"
|
||||
#include "fsfw/objectmanager.h"
|
||||
#include "fsfw/serviceinterface.h"
|
||||
#include "fsfw/tasks/TaskFactory.h"
|
||||
#include "fsfw/tmtcservices/TmTcMessage.h"
|
||||
|
||||
using namespace returnvalue;
|
||||
@@ -49,19 +50,16 @@ cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::fsmNacked() {
|
||||
}
|
||||
if (step == TransactionStep::TRANSACTION_START) {
|
||||
sourceParams.user.transactionIndication(transactionParams.id);
|
||||
step = TransactionStep::CRC_PROCEDURE;
|
||||
}
|
||||
if (step == TransactionStep::CRC_PROCEDURE) {
|
||||
result = checksumGeneration();
|
||||
if (result != OK) {
|
||||
// TODO: Some error handling
|
||||
addError(result);
|
||||
}
|
||||
step = TransactionStep::SENDING_METADATA;
|
||||
}
|
||||
if (step == TransactionStep::SENDING_METADATA) {
|
||||
result = prepareAndSendMetadataPdu();
|
||||
if (result != OK) {
|
||||
// TODO: Error handling
|
||||
addError(result);
|
||||
}
|
||||
fsmResult.callStatus = CallStatus::CALL_AGAIN;
|
||||
return fsmResult;
|
||||
@@ -69,10 +67,7 @@ cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::fsmNacked() {
|
||||
if (step == TransactionStep::SENDING_FILE_DATA) {
|
||||
bool noFdPdu = false;
|
||||
result = prepareAndSendNextFileDataPdu(noFdPdu);
|
||||
if (result != OK) {
|
||||
// TODO: Error handling
|
||||
}
|
||||
if (!noFdPdu) {
|
||||
if (result == OK and !noFdPdu) {
|
||||
fsmResult.callStatus = CallStatus::CALL_AGAIN;
|
||||
return fsmResult;
|
||||
}
|
||||
@@ -80,7 +75,7 @@ cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::fsmNacked() {
|
||||
if (step == TransactionStep::SENDING_EOF) {
|
||||
result = prepareAndSendEofPdu();
|
||||
if (result != OK) {
|
||||
// TODO: Error handling
|
||||
addError(result);
|
||||
}
|
||||
if (sourceParams.cfg.indicCfg.eofSentIndicRequired) {
|
||||
sourceParams.user.eofSentIndication(transactionParams.id);
|
||||
@@ -141,8 +136,7 @@ ReturnValue_t cfdp::SourceHandler::checksumGeneration() {
|
||||
params.size = readLen;
|
||||
auto result = sourceParams.user.vfs.readFromFile(params, buf.data(), buf.size());
|
||||
if (result != OK) {
|
||||
// TODO: I think this is a case for a filestore rejection, but it might sense to print
|
||||
// a warning or trigger an event because this should generally not happen
|
||||
addError(result);
|
||||
return FAILED;
|
||||
}
|
||||
crcCalc.add(buf.begin(), buf.begin() + readLen);
|
||||
@@ -171,6 +165,10 @@ ReturnValue_t cfdp::SourceHandler::transactionStart(PutRequest& putRequest, Remo
|
||||
const char* destNamePtr = putRequest.getDestName().getCString(transactionParams.destNameSize);
|
||||
std::strncpy(transactionParams.sourceName.data(), srcNamePtr, transactionParams.sourceNameSize);
|
||||
std::strncpy(transactionParams.destName.data(), destNamePtr, transactionParams.destNameSize);
|
||||
// Add 0 termination. The source and dest name size can not be larger than UINT8_MAX, so this
|
||||
// operation is safe.
|
||||
transactionParams.sourceName[transactionParams.sourceNameSize] = '\0';
|
||||
transactionParams.destName[transactionParams.destNameSize] = '\0';
|
||||
FilesystemParams params(transactionParams.sourceName.data());
|
||||
if (!sourceParams.user.vfs.fileExists(params)) {
|
||||
return FILE_DOES_NOT_EXIST;
|
||||
@@ -322,6 +320,10 @@ ReturnValue_t cfdp::SourceHandler::sendGenericPdu(const SerializeIF& pdu) {
|
||||
fsfwParams.tmStore->getFreeElement(&storeId, pdu.getSerializedSize(), &dataPtr);
|
||||
if (result != OK) {
|
||||
addError(result);
|
||||
fsmResult.callStatus = CallStatus::CALL_AFTER_DELAY;
|
||||
if (result == StorageManagerIF::DATA_STORAGE_FULL) {
|
||||
return TM_STORE_FULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
size_t serializedLen = 0;
|
||||
@@ -333,7 +335,12 @@ ReturnValue_t cfdp::SourceHandler::sendGenericPdu(const SerializeIF& pdu) {
|
||||
TmTcMessage tmMsg(storeId);
|
||||
result =
|
||||
fsfwParams.msgQueue->sendMessage(fsfwParams.packetDest.getReportReceptionQueue(), &tmMsg);
|
||||
if (result == OK) {
|
||||
if (result != OK) {
|
||||
fsmResult.callStatus = CallStatus::CALL_AFTER_DELAY;
|
||||
}
|
||||
if (result == MessageQueueIF::FULL) {
|
||||
return TARGET_MSG_QUEUE_FULL;
|
||||
} else if (result == OK) {
|
||||
fsmResult.packetsSent += 1;
|
||||
}
|
||||
return result;
|
||||
@@ -364,5 +371,6 @@ void cfdp::SourceHandler::addError(ReturnValue_t error) {
|
||||
if (fsmResult.errors < fsmResult.errorCodes.size()) {
|
||||
fsmResult.errorCodes[fsmResult.errors] = error;
|
||||
fsmResult.errors++;
|
||||
fsmResult.result = error;
|
||||
}
|
||||
}
|
||||
|
@@ -30,7 +30,6 @@ class SourceHandler {
|
||||
enum class TransactionStep : uint8_t {
|
||||
IDLE = 0,
|
||||
TRANSACTION_START = 1,
|
||||
CRC_PROCEDURE = 2,
|
||||
SENDING_METADATA = 3,
|
||||
SENDING_FILE_DATA = 4,
|
||||
SENDING_EOF = 5,
|
||||
|
@@ -35,7 +35,7 @@ struct MetadataRecvdParams {
|
||||
Fss fileSize{};
|
||||
const char* sourceFileName = "";
|
||||
const char* destFileName = "";
|
||||
size_t msgsToUserLen = 0;
|
||||
size_t numberOfMsgsToUser = 0;
|
||||
const MessageToUserTlv* msgsToUserArray = nullptr;
|
||||
};
|
||||
|
||||
|
@@ -12,7 +12,7 @@ namespace cfdp {
|
||||
enum class CfdpState { IDLE, BUSY_CLASS_1_NACKED, BUSY_CLASS_2_ACKED, SUSPENDED };
|
||||
|
||||
static constexpr uint8_t SSID = SUBSYSTEM_ID::CFDP;
|
||||
static constexpr uint8_t CID = CLASS_ID::CFDP;
|
||||
static constexpr uint8_t CID = CLASS_ID::CFDP_HANDLER;
|
||||
|
||||
struct PacketInfo {
|
||||
PacketInfo(PduType type, store_address_t storeId,
|
||||
@@ -58,6 +58,8 @@ static constexpr Event SERIALIZATION_ERROR = event::makeEvent(SSID, 2, severity:
|
||||
static constexpr Event FILESTORE_ERROR = event::makeEvent(SSID, 3, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] P1: Transaction step ID, P2: 0 for source file name, 1 for dest file name
|
||||
static constexpr Event FILENAME_TOO_LARGE_ERROR = event::makeEvent(SSID, 4, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] CFDP request handling failed. P2: Returncode.
|
||||
static constexpr Event HANDLING_CFDP_REQUEST_FAILED = event::makeEvent(SSID, 5, severity::LOW);
|
||||
|
||||
} // namespace events
|
||||
|
||||
@@ -67,6 +69,8 @@ static constexpr ReturnValue_t FILE_SEGMENT_LEN_INVALID = returnvalue::makeCode(
|
||||
static constexpr ReturnValue_t SOURCE_NAME_EMPTY = returnvalue::makeCode(CID, 3);
|
||||
static constexpr ReturnValue_t DEST_NAME_EMPTY = returnvalue::makeCode(CID, 4);
|
||||
static constexpr ReturnValue_t WRONG_REMOTE_CFG_ENTITY_ID = returnvalue::makeCode(CID, 5);
|
||||
static constexpr ReturnValue_t TARGET_MSG_QUEUE_FULL = returnvalue::makeCode(CID, 6);
|
||||
static constexpr ReturnValue_t TM_STORE_FULL = returnvalue::makeCode(CID, 7);
|
||||
|
||||
} // namespace cfdp
|
||||
#endif // FSFW_CFDP_HANDLER_DEFS_H
|
||||
|
@@ -30,7 +30,7 @@ struct RemoteEntityCfg {
|
||||
RemoteEntityCfg() = default;
|
||||
explicit RemoteEntityCfg(EntityId id) : remoteId(std::move(id)) {}
|
||||
EntityId remoteId;
|
||||
size_t maxFileSegmentLen = 2048;
|
||||
size_t maxFileSegmentLen = 1024;
|
||||
bool closureRequested = false;
|
||||
bool crcOnTransmission = false;
|
||||
TransmissionMode defaultTransmissionMode = TransmissionMode::UNACKNOWLEDGED;
|
||||
|
@@ -21,7 +21,7 @@ void MetadataGenericInfo::setClosureRequested(bool closureRequested_) {
|
||||
closureRequested = closureRequested_;
|
||||
}
|
||||
|
||||
cfdp::Fss& MetadataGenericInfo::getFileSize() { return fileSize; }
|
||||
const cfdp::Fss& MetadataGenericInfo::getFileSize() const { return fileSize; }
|
||||
|
||||
size_t MetadataGenericInfo::getSerializedSize(bool fssLarge) {
|
||||
// 1 byte + minimal FSS 4 bytes
|
||||
@@ -31,3 +31,5 @@ size_t MetadataGenericInfo::getSerializedSize(bool fssLarge) {
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
cfdp::Fss& MetadataGenericInfo::getMutFileSize() { return fileSize; }
|
||||
|
@@ -22,7 +22,9 @@ class MetadataGenericInfo {
|
||||
[[nodiscard]] bool isClosureRequested() const;
|
||||
void setClosureRequested(bool closureRequested = false);
|
||||
|
||||
cfdp::Fss& getFileSize();
|
||||
[[nodiscard]] const cfdp::Fss& getFileSize() const;
|
||||
|
||||
cfdp::Fss& getMutFileSize();
|
||||
|
||||
private:
|
||||
bool closureRequested = false;
|
||||
|
@@ -25,7 +25,7 @@ ReturnValue_t MetadataPduReader::parseData() {
|
||||
remSize -= 1;
|
||||
buf += 1;
|
||||
auto endianness = getEndianness();
|
||||
result = info.getFileSize().deSerialize(&buf, &remSize, endianness);
|
||||
result = info.getMutFileSize().deSerialize(&buf, &remSize, endianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -63,3 +63,5 @@ size_t MetadataPduReader::getNumberOfParsedOptions() const { return parsedOption
|
||||
const cfdp::StringLv& MetadataPduReader::getSourceFileName() const { return srcFileName; }
|
||||
|
||||
const cfdp::StringLv& MetadataPduReader::getDestFileName() const { return destFileName; }
|
||||
|
||||
const MetadataGenericInfo& MetadataPduReader::getGenericInfo() const { return info; }
|
||||
|
@@ -11,6 +11,7 @@ class MetadataPduReader : public FileDirectiveReader {
|
||||
|
||||
ReturnValue_t parseData() override;
|
||||
|
||||
[[nodiscard]] const MetadataGenericInfo& getGenericInfo() const;
|
||||
[[nodiscard]] const cfdp::StringLv& getSourceFileName() const;
|
||||
[[nodiscard]] const cfdp::StringLv& getDestFileName() const;
|
||||
|
||||
|
@@ -95,3 +95,5 @@ cfdp::Lv& cfdp::Lv::operator=(cfdp::Lv&& other) noexcept {
|
||||
}
|
||||
|
||||
size_t cfdp::Lv::getValueLen() const { return getSerializedSize() - 1; }
|
||||
|
||||
bool cfdp::Lv::isEmpty() const { return zeroLen; }
|
||||
|
@@ -50,6 +50,8 @@ class Lv : public SerializeIF {
|
||||
*/
|
||||
const uint8_t* getValue(size_t* size) const;
|
||||
|
||||
bool isEmpty() const;
|
||||
|
||||
private:
|
||||
bool zeroLen = true;
|
||||
SerialBufferAdapter<uint8_t> value;
|
||||
|
@@ -16,7 +16,7 @@ bool MessageToUserTlv::isReservedCfdpMessage(uint8_t& messageType, const uint8_t
|
||||
if (cfdp::Tlv::getLengthField() < 5) {
|
||||
return false;
|
||||
}
|
||||
if (std::strcmp(reinterpret_cast<const char*>(getValue()), "cfdp") == 0) {
|
||||
if (std::strncmp(reinterpret_cast<const char*>(getValue()), "cfdp", 4) == 0) {
|
||||
messageType = getValue()[4];
|
||||
if (msgDataStart != nullptr) {
|
||||
*msgDataStart = getValue() + 5;
|
||||
|
@@ -54,6 +54,7 @@ ReturnValue_t cfdp::Tlv::deSerialize(const uint8_t **buffer, size_t *size,
|
||||
return STREAM_TOO_SHORT;
|
||||
}
|
||||
|
||||
rawData = *buffer;
|
||||
uint8_t rawType = **buffer;
|
||||
if (not checkType(rawType)) {
|
||||
return INVALID_TLV_TYPE;
|
||||
@@ -102,3 +103,5 @@ void cfdp::Tlv::setValue(uint8_t *value, size_t len) {
|
||||
uint8_t cfdp::Tlv::getLengthField() const { return this->value.getSerializedSize() - 1; }
|
||||
|
||||
void cfdp::Tlv::setType(TlvType type) { this->type = type; }
|
||||
|
||||
const uint8_t *cfdp::Tlv::getRawData() const { return rawData; }
|
||||
|
@@ -47,6 +47,7 @@ class Tlv : public TlvIF {
|
||||
void setValue(uint8_t *value, size_t len);
|
||||
|
||||
[[nodiscard]] const uint8_t *getValue() const;
|
||||
[[nodiscard]] const uint8_t *getRawData() const;
|
||||
void setType(TlvType type);
|
||||
[[nodiscard]] TlvType getType() const override;
|
||||
[[nodiscard]] uint8_t getLengthField() const override;
|
||||
@@ -55,6 +56,7 @@ class Tlv : public TlvIF {
|
||||
bool checkType(uint8_t rawType);
|
||||
|
||||
bool zeroLen = true;
|
||||
const uint8_t *rawData = nullptr;
|
||||
TlvType type = TlvType::INVALID_TLV;
|
||||
SerialBufferAdapter<uint8_t> value;
|
||||
};
|
||||
|
@@ -85,6 +85,7 @@ class DeviceHandlerIF {
|
||||
static const ReturnValue_t NO_REPLY_EXPECTED = MAKE_RETURN_CODE(0xA8);
|
||||
static const ReturnValue_t NON_OP_TEMPERATURE = MAKE_RETURN_CODE(0xA9);
|
||||
static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xAA);
|
||||
static const ReturnValue_t NON_OP_STATE_OF_CHARGE = MAKE_RETURN_CODE(0xAB);
|
||||
|
||||
// Standard codes used in scanForReply
|
||||
static const ReturnValue_t CHECKSUM_ERROR = MAKE_RETURN_CODE(0xB0);
|
||||
|
@@ -21,7 +21,7 @@ TcpTmTcBridge::TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
|
||||
: TmTcBridge("TCP TMTC Bridge", objectId, tcDestination, msgQueueDepth, tmStoreId, tcStoreId) {
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
// Connection is always up, TM is requested by connecting to server and receiving packets
|
||||
registerCommConnect();
|
||||
TmTcBridge::registerCommConnect();
|
||||
}
|
||||
|
||||
ReturnValue_t TcpTmTcBridge::initialize() {
|
||||
|
@@ -123,6 +123,7 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
|
||||
StorageManagerIF* tmStore = nullptr;
|
||||
|
||||
private:
|
||||
//! [EXPORT] : [SKIP]
|
||||
static constexpr ReturnValue_t CONN_BROKEN = returnvalue::makeCode(1, 0);
|
||||
//! TMTC bridge is cached.
|
||||
object_id_t tmtcBridgeId = objects::NO_OBJECT;
|
||||
|
@@ -38,6 +38,8 @@ class PowerSwitcherComponent : public SystemObject,
|
||||
|
||||
protected:
|
||||
PowerSwitcher switcher;
|
||||
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t *msToReachTheMode) override;
|
||||
|
||||
private:
|
||||
MessageQueueIF *queue = nullptr;
|
||||
@@ -56,8 +58,6 @@ class PowerSwitcherComponent : public SystemObject,
|
||||
|
||||
[[nodiscard]] MessageQueueId_t getCommandQueue() const override;
|
||||
void getMode(Mode_t *mode, Submode_t *submode) override;
|
||||
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t *msToReachTheMode) override;
|
||||
void startTransition(Mode_t mode, Submode_t submode) override;
|
||||
virtual void performFaultyOperation();
|
||||
void setToExternalControl() override;
|
||||
|
@@ -61,7 +61,8 @@ enum : uint8_t {
|
||||
HAS_ACTIONS_IF, // HF
|
||||
DEVICE_COMMUNICATION_IF, // DC
|
||||
BSP, // BSP
|
||||
CFDP, // CFDP
|
||||
CFDP_BASE, // CFDP
|
||||
CFDP_HANDLER, // CFDP
|
||||
TIME_STAMPER_IF, // TSI
|
||||
SGP4PROPAGATOR_CLASS, // SGP4
|
||||
MUTEX_IF, // MUX
|
||||
|
@@ -107,14 +107,6 @@ uint8_t* SerialBufferAdapter<count_t>::getBuffer() {
|
||||
|
||||
template <typename count_t>
|
||||
const uint8_t* SerialBufferAdapter<count_t>::getConstBuffer() const {
|
||||
if (constBuffer == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "SerialBufferAdapter::getConstBuffer:"
|
||||
" Buffers are unitialized!"
|
||||
<< std::endl;
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
return constBuffer;
|
||||
}
|
||||
|
||||
|
@@ -63,7 +63,17 @@ class SerialBufferAdapter : public SerializeIF {
|
||||
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
Endianness streamEndianness) override;
|
||||
|
||||
/**
|
||||
* Please note that this function can also return a nullpointer in case the length field contains
|
||||
* 0.
|
||||
* @return
|
||||
*/
|
||||
uint8_t* getBuffer();
|
||||
/**
|
||||
* Please note that this function can also return a nullpointer in case the length field contains
|
||||
* 0.
|
||||
* @return
|
||||
*/
|
||||
[[nodiscard]] const uint8_t* getConstBuffer() const;
|
||||
void setConstBuffer(const uint8_t* buf, count_t bufLen);
|
||||
|
||||
|
@@ -89,7 +89,7 @@ ReturnValue_t LocalPool::deleteData(store_address_t storeId) {
|
||||
ReturnValue_t status = returnvalue::OK;
|
||||
size_type pageSize = getSubpoolElementSize(storeId.poolIndex);
|
||||
if ((pageSize != 0) and (storeId.packetIndex < numberOfElements[storeId.poolIndex])) {
|
||||
uint16_t packetPosition = getRawPosition(storeId);
|
||||
size_type packetPosition = getRawPosition(storeId);
|
||||
uint8_t* ptr = &store[storeId.poolIndex][packetPosition];
|
||||
std::memset(ptr, 0, pageSize);
|
||||
// Set free list
|
||||
|
@@ -57,6 +57,13 @@ ReturnValue_t PusTmReader::parseData(bool crcCheck) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
if (crcCheck) {
|
||||
uint16_t crc16 = CRC::crc16ccitt(spReader.getFullData(), getFullPacketLen());
|
||||
if (crc16 != 0) {
|
||||
// Checksum failure
|
||||
return PusIF::INVALID_CRC_16;
|
||||
}
|
||||
}
|
||||
size_t currentOffset = SpacePacketReader::getHeaderLen();
|
||||
pointers.secHeaderStart = pointers.spHeaderStart + currentOffset;
|
||||
currentOffset += PusTmIF::MIN_SEC_HEADER_LEN;
|
||||
@@ -77,13 +84,6 @@ ReturnValue_t PusTmReader::parseData(bool crcCheck) {
|
||||
}
|
||||
currentOffset += sourceDataLen;
|
||||
pointers.crcStart = pointers.spHeaderStart + currentOffset;
|
||||
if (crcCheck) {
|
||||
uint16_t crc16 = CRC::crc16ccitt(spReader.getFullData(), getFullPacketLen());
|
||||
if (crc16 != 0) {
|
||||
// Checksum failure
|
||||
return PusIF::INVALID_CRC_16;
|
||||
}
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
bool PusTmReader::isNull() const { return spReader.isNull() or pointers.secHeaderStart == nullptr; }
|
||||
|
@@ -23,18 +23,8 @@ TmTcBridge::TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDes
|
||||
|
||||
TmTcBridge::~TmTcBridge() { QueueFactory::instance()->deleteMessageQueue(tmTcReceptionQueue); }
|
||||
|
||||
ReturnValue_t TmTcBridge::setNumberOfSentPacketsPerCycle(uint8_t sentPacketsPerCycle) {
|
||||
if (sentPacketsPerCycle <= LIMIT_STORED_DATA_SENT_PER_CYCLE) {
|
||||
this->sentPacketsPerCycle = sentPacketsPerCycle;
|
||||
return returnvalue::OK;
|
||||
} else {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "TmTcBridge::setNumberOfSentPacketsPerCycle: Number of "
|
||||
<< "packets sent per cycle exceeds limits. "
|
||||
<< "Keeping default value." << std::endl;
|
||||
#endif
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
void TmTcBridge::setNumberOfSentPacketsPerCycle(uint32_t sentPacketsPerCycle_) {
|
||||
this->sentPacketsPerCycle = sentPacketsPerCycle_;
|
||||
}
|
||||
|
||||
ReturnValue_t TmTcBridge::setMaxNumberOfPacketsStored(unsigned int maxNumberOfPacketsStored) {
|
||||
@@ -144,8 +134,8 @@ ReturnValue_t TmTcBridge::handleTmQueue() {
|
||||
#endif
|
||||
#endif /* FSFW_VERBOSE_LEVEL >= 3 */
|
||||
|
||||
if (communicationLinkUp == false or packetSentCounter >= sentPacketsPerCycle) {
|
||||
ReturnValue_t result = storeDownlinkData(&message);
|
||||
if (!communicationLinkUp or packetSentCounter >= sentPacketsPerCycle) {
|
||||
result = storeDownlinkData(&message);
|
||||
if (result != returnvalue::OK) {
|
||||
tmStore->deleteData(message.getStorageId());
|
||||
}
|
||||
|
@@ -15,10 +15,9 @@ class TmTcBridge : public AcceptsTelemetryIF,
|
||||
public ExecutableObjectIF,
|
||||
public SystemObject {
|
||||
public:
|
||||
static constexpr uint8_t LIMIT_STORED_DATA_SENT_PER_CYCLE = 15;
|
||||
static constexpr unsigned int LIMIT_DOWNLINK_PACKETS_STORED = 500;
|
||||
|
||||
static constexpr uint8_t DEFAULT_STORED_DATA_SENT_PER_CYCLE = 5;
|
||||
static constexpr uint8_t DEFAULT_STORED_DATA_SENT_PER_CYCLE = 20;
|
||||
static constexpr uint8_t DEFAULT_DOWNLINK_PACKETS_STORED = 10;
|
||||
|
||||
TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDestination,
|
||||
@@ -32,7 +31,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
|
||||
* @return -@c returnvalue::OK if value was set successfully
|
||||
* -@c returnvalue::FAILED otherwise, stored value stays the same
|
||||
*/
|
||||
ReturnValue_t setNumberOfSentPacketsPerCycle(uint8_t sentPacketsPerCycle);
|
||||
void setNumberOfSentPacketsPerCycle(uint32_t sentPacketsPerCycle);
|
||||
|
||||
/**
|
||||
* Set number of packets sent per performOperation().Please note that this
|
||||
@@ -151,7 +150,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
|
||||
* This FIFO can be used to store downlink data which can not be sent at the moment.
|
||||
*/
|
||||
DynamicFIFO<store_address_t>* tmFifo = nullptr;
|
||||
uint8_t sentPacketsPerCycle = DEFAULT_STORED_DATA_SENT_PER_CYCLE;
|
||||
uint32_t sentPacketsPerCycle = DEFAULT_STORED_DATA_SENT_PER_CYCLE;
|
||||
unsigned int maxNumberOfPacketsStored = DEFAULT_DOWNLINK_PACKETS_STORED;
|
||||
};
|
||||
|
||||
|
@@ -282,7 +282,7 @@ ReturnValue_t SpiComIF::handlePollingSendOperation(uint8_t *recvPtr, SPI_HandleT
|
||||
#endif
|
||||
#endif
|
||||
spiCookie.setTransferState(spi::TransferStates::FAILURE);
|
||||
return spi::HAL_TIMEOUT_RETVAL;
|
||||
return spi::TIMEOUT;
|
||||
}
|
||||
case (HAL_ERROR):
|
||||
default: {
|
||||
@@ -296,7 +296,7 @@ ReturnValue_t SpiComIF::handlePollingSendOperation(uint8_t *recvPtr, SPI_HandleT
|
||||
#endif
|
||||
#endif
|
||||
spiCookie.setTransferState(spi::TransferStates::FAILURE);
|
||||
return spi::HAL_ERROR_RETVAL;
|
||||
return spi::GENERIC_ERROR;
|
||||
}
|
||||
}
|
||||
return returnvalue::OK;
|
||||
|
@@ -9,11 +9,6 @@
|
||||
|
||||
namespace spi {
|
||||
|
||||
static constexpr uint8_t HAL_SPI_ID = CLASS_ID::HAL_SPI;
|
||||
static constexpr ReturnValue_t HAL_TIMEOUT_RETVAL = returnvalue::makeCode(HAL_SPI_ID, 0);
|
||||
static constexpr ReturnValue_t HAL_BUSY_RETVAL = returnvalue::makeCode(HAL_SPI_ID, 1);
|
||||
static constexpr ReturnValue_t HAL_ERROR_RETVAL = returnvalue::makeCode(HAL_SPI_ID, 2);
|
||||
|
||||
enum class TransferStates { IDLE, WAIT, SUCCESS, FAILURE };
|
||||
|
||||
enum SpiBus { SPI_1, SPI_2 };
|
||||
|
@@ -134,7 +134,7 @@ TEST_CASE("CFDP Dest Handler", "[cfdp]") {
|
||||
}
|
||||
|
||||
SECTION("Idle State Machine Iteration") {
|
||||
auto res = destHandler.performStateMachine();
|
||||
auto res = destHandler.stateMachine();
|
||||
CHECK(res.result == OK);
|
||||
CHECK(res.callStatus == CallStatus::CALL_AFTER_DELAY);
|
||||
CHECK(res.errors == 0);
|
||||
@@ -143,23 +143,23 @@ TEST_CASE("CFDP Dest Handler", "[cfdp]") {
|
||||
}
|
||||
|
||||
SECTION("Empty File Transfer") {
|
||||
const DestHandler::FsmResult& res = destHandler.performStateMachine();
|
||||
const DestHandler::FsmResult& res = destHandler.stateMachine();
|
||||
CHECK(res.result == OK);
|
||||
Fss cfdpFileSize(0);
|
||||
metadataPreparation(cfdpFileSize, ChecksumType::NULL_CHECKSUM);
|
||||
destHandler.performStateMachine();
|
||||
destHandler.stateMachine();
|
||||
metadataCheck(res, "hello.txt", "hello-cpy.txt", 0);
|
||||
destHandler.performStateMachine();
|
||||
destHandler.stateMachine();
|
||||
REQUIRE(res.callStatus == CallStatus::CALL_AFTER_DELAY);
|
||||
auto transactionId = destHandler.getTransactionId();
|
||||
eofPreparation(cfdpFileSize, 0);
|
||||
// After EOF, operation is done because no closure was requested
|
||||
destHandler.performStateMachine();
|
||||
destHandler.stateMachine();
|
||||
eofCheck(res, transactionId);
|
||||
}
|
||||
|
||||
SECTION("Small File Transfer") {
|
||||
const DestHandler::FsmResult& res = destHandler.performStateMachine();
|
||||
const DestHandler::FsmResult& res = destHandler.stateMachine();
|
||||
CHECK(res.result == OK);
|
||||
std::string fileData = "hello test data";
|
||||
etl::crc32 crcCalc;
|
||||
@@ -167,9 +167,9 @@ TEST_CASE("CFDP Dest Handler", "[cfdp]") {
|
||||
uint32_t crc32 = crcCalc.value();
|
||||
Fss cfdpFileSize(fileData.size());
|
||||
metadataPreparation(cfdpFileSize, ChecksumType::CRC_32);
|
||||
destHandler.performStateMachine();
|
||||
destHandler.stateMachine();
|
||||
metadataCheck(res, "hello.txt", "hello-cpy.txt", fileData.size());
|
||||
destHandler.performStateMachine();
|
||||
destHandler.stateMachine();
|
||||
REQUIRE(res.callStatus == CallStatus::CALL_AFTER_DELAY);
|
||||
auto transactionId = destHandler.getTransactionId();
|
||||
Fss offset(0);
|
||||
@@ -180,16 +180,16 @@ TEST_CASE("CFDP Dest Handler", "[cfdp]") {
|
||||
REQUIRE(fdPduCreator.serialize(buf, serLen, fdPduCreator.getSerializedSize()) == OK);
|
||||
PacketInfo packetInfo(fdPduCreator.getPduType(), storeId, std::nullopt);
|
||||
packetInfoList.push_back(packetInfo);
|
||||
destHandler.performStateMachine();
|
||||
destHandler.stateMachine();
|
||||
fileDataPduCheck(res, {storeId});
|
||||
eofPreparation(cfdpFileSize, crc32);
|
||||
// After EOF, operation is done because no closure was requested
|
||||
destHandler.performStateMachine();
|
||||
destHandler.stateMachine();
|
||||
eofCheck(res, transactionId);
|
||||
}
|
||||
|
||||
SECTION("Segmented File Transfer") {
|
||||
const DestHandler::FsmResult& res = destHandler.performStateMachine();
|
||||
const DestHandler::FsmResult& res = destHandler.stateMachine();
|
||||
CHECK(res.result == OK);
|
||||
std::random_device dev;
|
||||
std::mt19937 rng(dev());
|
||||
@@ -203,9 +203,9 @@ TEST_CASE("CFDP Dest Handler", "[cfdp]") {
|
||||
uint32_t crc32 = crcCalc.value();
|
||||
Fss cfdpFileSize(largerFileData.size());
|
||||
metadataPreparation(cfdpFileSize, ChecksumType::CRC_32);
|
||||
destHandler.performStateMachine();
|
||||
destHandler.stateMachine();
|
||||
metadataCheck(res, "hello.txt", "hello-cpy.txt", largerFileData.size());
|
||||
destHandler.performStateMachine();
|
||||
destHandler.stateMachine();
|
||||
REQUIRE(res.callStatus == CallStatus::CALL_AFTER_DELAY);
|
||||
auto transactionId = destHandler.getTransactionId();
|
||||
|
||||
@@ -234,11 +234,11 @@ TEST_CASE("CFDP Dest Handler", "[cfdp]") {
|
||||
packetInfoList.push_back(packetInfo);
|
||||
}
|
||||
|
||||
destHandler.performStateMachine();
|
||||
destHandler.stateMachine();
|
||||
fileDataPduCheck(res, idsToCheck);
|
||||
eofPreparation(cfdpFileSize, crc32);
|
||||
// After EOF, operation is done because no closure was requested
|
||||
destHandler.performStateMachine();
|
||||
destHandler.stateMachine();
|
||||
eofCheck(res, transactionId);
|
||||
}
|
||||
}
|
@@ -40,10 +40,10 @@ TEST_CASE("Reserved Message Parser", "[cfdp]") {
|
||||
serLen = 0;
|
||||
ReturnValue_t result = creator.serializeBe(buffer.data(), serLen, buffer.size());
|
||||
CHECK(result == returnvalue::OK);
|
||||
arrayprinter::print(buffer.data(), serLen);
|
||||
|
||||
MessageToUserTlv msgToUser;
|
||||
CHECK(msgToUser.deSerializeBe(buffer.data(), serLen, buffer.size()) == OK);
|
||||
ReservedMessageParser parser(ipcStore, msgQueue, destQueueId);
|
||||
REQUIRE(parser.parse(buffer.data(), serLen) == OK);
|
||||
REQUIRE(parser.parse(&msgToUser, 1) == OK);
|
||||
CommandMessage msg;
|
||||
CHECK(msgQueue.wasMessageSent());
|
||||
CHECK(msgQueue.numberOfSentMessages() == 1);
|
||||
|
@@ -63,7 +63,7 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") {
|
||||
PutRequest putRequest(remoteId, srcNameLv, destNameLv);
|
||||
CHECK(sourceHandler.initialize() == OK);
|
||||
|
||||
auto onePduSentCheck = [&](SourceHandler::FsmResult& fsmResult, TmTcMessage& tmtcMessage,
|
||||
auto onePduSentCheck = [&](const SourceHandler::FsmResult& fsmResult, TmTcMessage& tmtcMessage,
|
||||
const uint8_t** pduPtr) {
|
||||
CHECK(fsmResult.errors == 0);
|
||||
CHECK(fsmResult.packetsSent == 1);
|
||||
@@ -74,9 +74,10 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") {
|
||||
*pduPtr = accessor.second.data();
|
||||
return std::move(accessor);
|
||||
};
|
||||
auto genericMetadataCheck = [&](SourceHandler::FsmResult& fsmResult, size_t expectedFileSize,
|
||||
uint16_t expectedSeqNum) {
|
||||
auto genericMetadataCheck = [&](const SourceHandler::FsmResult& fsmResult,
|
||||
size_t expectedFileSize, uint16_t expectedSeqNum) {
|
||||
CHECK(fsmResult.errors == 0);
|
||||
CHECK(fsmResult.callStatus == CallStatus::CALL_AGAIN);
|
||||
TmTcMessage tmtcMessage;
|
||||
const uint8_t* pduPtr;
|
||||
auto accessor = onePduSentCheck(fsmResult, tmtcMessage, &pduPtr);
|
||||
@@ -108,9 +109,10 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") {
|
||||
CHECK(!metadataInfo.isClosureRequested());
|
||||
mqMock.clearMessages();
|
||||
};
|
||||
auto genericEofCheck = [&](SourceHandler::FsmResult& fsmResult, size_t expectedFileSize,
|
||||
auto genericEofCheck = [&](const SourceHandler::FsmResult& fsmResult, size_t expectedFileSize,
|
||||
uint32_t expectedChecksum, uint16_t expectedSeqNum) {
|
||||
CHECK(fsmResult.errors == 0);
|
||||
CHECK(fsmResult.callStatus == CallStatus::CALL_AGAIN);
|
||||
TmTcMessage tmtcMessage;
|
||||
const uint8_t* pduPtr;
|
||||
auto accessor = onePduSentCheck(fsmResult, tmtcMessage, &pduPtr);
|
||||
@@ -126,12 +128,20 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") {
|
||||
auto transactionId = TransactionId(localId, seqNum);
|
||||
CHECK(userMock.eofSentRecvd.size() == 1);
|
||||
CHECK(userMock.eofSentRecvd.back() == transactionId);
|
||||
CHECK(userMock.finishedRecvd.size() == 1);
|
||||
CHECK(userMock.finishedRecvd.back().first == transactionId);
|
||||
CHECK(eofInfo.getChecksum() == expectedChecksum);
|
||||
CHECK(eofInfo.getConditionCode() == ConditionCode::NO_ERROR);
|
||||
CHECK(eofInfo.getFileSize().value() == expectedFileSize);
|
||||
};
|
||||
auto genericNoticeOfCompletionCheck = [&](const SourceHandler::FsmResult& fsmResult,
|
||||
uint16_t expectedSeqNum) {
|
||||
CHECK(fsmResult.callStatus == CallStatus::DONE);
|
||||
CHECK(userMock.finishedRecvd.size() == 1);
|
||||
CHECK(userMock.finishedRecvd.back().first ==
|
||||
TransactionId(localId, TransactionSeqNum(cfdp::WidthInBytes::TWO_BYTES, expectedSeqNum)));
|
||||
CHECK(sourceHandler.getStep() == SourceHandler::TransactionStep::IDLE);
|
||||
CHECK(sourceHandler.getState() == CfdpState::IDLE);
|
||||
};
|
||||
|
||||
SECTION("Test Basic") {
|
||||
CHECK(sourceHandler.getState() == CfdpState::IDLE);
|
||||
CHECK(sourceHandler.getStep() == SourceHandler::TransactionStep::IDLE);
|
||||
@@ -141,16 +151,17 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") {
|
||||
CHECK(sourceHandler.transactionStart(putRequest, cfg) == OK);
|
||||
|
||||
size_t expectedFileSize = 0;
|
||||
SourceHandler::FsmResult& fsmResult = sourceHandler.stateMachine();
|
||||
const SourceHandler::FsmResult& fsmResult = sourceHandler.stateMachine();
|
||||
// Verify metadata PDU was sent.
|
||||
genericMetadataCheck(fsmResult, expectedFileSize, 0);
|
||||
|
||||
fsmResult = sourceHandler.stateMachine();
|
||||
sourceHandler.stateMachine();
|
||||
// Verify EOF PDU was sent. No file data PDU is sent for an empty file and the checksum is 0.
|
||||
genericEofCheck(fsmResult, expectedFileSize, 0, 0);
|
||||
|
||||
CHECK(sourceHandler.getStep() == SourceHandler::TransactionStep::IDLE);
|
||||
CHECK(sourceHandler.getState() == CfdpState::IDLE);
|
||||
// Verify notice of completion.
|
||||
sourceHandler.stateMachine();
|
||||
genericNoticeOfCompletionCheck(fsmResult, 0);
|
||||
}
|
||||
|
||||
SECTION("Transfer small file") {
|
||||
@@ -161,13 +172,13 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") {
|
||||
FileOpParams params(srcFileName.c_str(), expectedFileSize);
|
||||
fsMock.writeToFile(params, reinterpret_cast<const uint8_t*>(fileContent.data()));
|
||||
CHECK(sourceHandler.transactionStart(putRequest, cfg) == OK);
|
||||
SourceHandler::FsmResult& fsmResult = sourceHandler.stateMachine();
|
||||
const SourceHandler::FsmResult& fsmResult = sourceHandler.stateMachine();
|
||||
|
||||
// Verify metadata PDU was sent.
|
||||
genericMetadataCheck(fsmResult, expectedFileSize, expectedSeqNum);
|
||||
|
||||
// Verify that a small file data PDU was sent.
|
||||
fsmResult = sourceHandler.stateMachine();
|
||||
sourceHandler.stateMachine();
|
||||
TmTcMessage tmtcMessage;
|
||||
const uint8_t* pduPtr;
|
||||
auto accessor = onePduSentCheck(fsmResult, tmtcMessage, &pduPtr);
|
||||
@@ -185,15 +196,16 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") {
|
||||
CHECK(dataReadBack == fileContent);
|
||||
mqMock.clearMessages();
|
||||
|
||||
fsmResult = sourceHandler.stateMachine();
|
||||
sourceHandler.stateMachine();
|
||||
|
||||
etl::crc32 crcCalc;
|
||||
crcCalc.add(fileContent.data(), fileContent.data() + fileContent.size());
|
||||
// Verify EOF PDU was sent.
|
||||
genericEofCheck(fsmResult, expectedFileSize, crcCalc.value(), expectedSeqNum);
|
||||
|
||||
CHECK(sourceHandler.getStep() == SourceHandler::TransactionStep::IDLE);
|
||||
CHECK(sourceHandler.getState() == CfdpState::IDLE);
|
||||
// Verify notice of completion.
|
||||
sourceHandler.stateMachine();
|
||||
genericNoticeOfCompletionCheck(fsmResult, expectedSeqNum);
|
||||
}
|
||||
|
||||
SECTION("Transfer two segment file") {
|
||||
@@ -212,16 +224,17 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") {
|
||||
FileOpParams params(srcFileName.c_str(), expectedFileSize);
|
||||
fsMock.writeToFile(params, reinterpret_cast<const uint8_t*>(largerFileData.data()));
|
||||
CHECK(sourceHandler.transactionStart(putRequest, cfg) == OK);
|
||||
SourceHandler::FsmResult& fsmResult = sourceHandler.stateMachine();
|
||||
const SourceHandler::FsmResult& fsmResult = sourceHandler.stateMachine();
|
||||
// Verify metadata PDU was sent.
|
||||
genericMetadataCheck(fsmResult, expectedFileSize, expectedSeqNum);
|
||||
|
||||
// Check first file data PDU. It should have the maximum file segment size.
|
||||
fsmResult = sourceHandler.stateMachine();
|
||||
sourceHandler.stateMachine();
|
||||
TmTcMessage tmtcMessage;
|
||||
const uint8_t* pduPtr;
|
||||
FileDataInfo fdInfo;
|
||||
{
|
||||
CHECK(fsmResult.callStatus == CallStatus::CALL_AGAIN);
|
||||
auto accessor = onePduSentCheck(fsmResult, tmtcMessage, &pduPtr);
|
||||
FileDataReader fdReader(pduPtr, accessor.second.size(), fdInfo);
|
||||
// 10 byte PDU header, 4 byte offset, 255 byte file data
|
||||
@@ -239,31 +252,35 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") {
|
||||
mqMock.clearMessages();
|
||||
|
||||
// Check second file data PDU.
|
||||
fsmResult = sourceHandler.stateMachine();
|
||||
auto accessor = onePduSentCheck(fsmResult, tmtcMessage, &pduPtr);
|
||||
FileDataReader fdReader(pduPtr, accessor.second.size(), fdInfo);
|
||||
// 10 byte PDU header, 4 byte offset, remaining file data (400 - 255 == 145).
|
||||
CHECK(accessor.second.size() == 10 + 4 + largerFileData.size() - MAX_FILE_SEGMENT_SIZE);
|
||||
CHECK(fdReader.parseData() == OK);
|
||||
CHECK(fdInfo.getOffset().value() == MAX_FILE_SEGMENT_SIZE);
|
||||
size_t fileDataSize = 0;
|
||||
const uint8_t* fileData = fdInfo.getFileData(&fileDataSize);
|
||||
// Maximum file segment size.
|
||||
REQUIRE(fileDataSize == largerFileData.size() - MAX_FILE_SEGMENT_SIZE);
|
||||
for (unsigned i = 0; i < fileDataSize; i++) {
|
||||
CHECK(fileData[i] == largerFileData[MAX_FILE_SEGMENT_SIZE + i]);
|
||||
sourceHandler.stateMachine();
|
||||
{
|
||||
CHECK(fsmResult.callStatus == CallStatus::CALL_AGAIN);
|
||||
auto accessor = onePduSentCheck(fsmResult, tmtcMessage, &pduPtr);
|
||||
FileDataReader fdReader(pduPtr, accessor.second.size(), fdInfo);
|
||||
// 10 byte PDU header, 4 byte offset, remaining file data (400 - 255 == 145).
|
||||
CHECK(accessor.second.size() == 10 + 4 + largerFileData.size() - MAX_FILE_SEGMENT_SIZE);
|
||||
CHECK(fdReader.parseData() == OK);
|
||||
CHECK(fdInfo.getOffset().value() == MAX_FILE_SEGMENT_SIZE);
|
||||
size_t fileDataSize = 0;
|
||||
const uint8_t* fileData = fdInfo.getFileData(&fileDataSize);
|
||||
// Maximum file segment size.
|
||||
REQUIRE(fileDataSize == largerFileData.size() - MAX_FILE_SEGMENT_SIZE);
|
||||
for (unsigned i = 0; i < fileDataSize; i++) {
|
||||
CHECK(fileData[i] == largerFileData[MAX_FILE_SEGMENT_SIZE + i]);
|
||||
}
|
||||
}
|
||||
mqMock.clearMessages();
|
||||
|
||||
// Check EOF and verify checksum.
|
||||
fsmResult = sourceHandler.stateMachine();
|
||||
sourceHandler.stateMachine();
|
||||
|
||||
etl::crc32 crcCalc;
|
||||
crcCalc.add(largerFileData.data(), largerFileData.data() + largerFileData.size());
|
||||
// Verify EOF PDU was sent.
|
||||
genericEofCheck(fsmResult, expectedFileSize, crcCalc.value(), expectedSeqNum);
|
||||
|
||||
CHECK(sourceHandler.getStep() == SourceHandler::TransactionStep::IDLE);
|
||||
CHECK(sourceHandler.getState() == CfdpState::IDLE);
|
||||
// Verify notice of completion.
|
||||
sourceHandler.stateMachine();
|
||||
genericNoticeOfCompletionCheck(fsmResult, expectedSeqNum);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user