60 m_txn_class(Cfdp::
Class::CLASS_1),
69 m_keep(Cfdp::
Keep::KEEP),
70 m_chan_num(channelId),
77 m_cfdpManager(manager),
82 memset(&this->m_state_data, 0,
sizeof(this->m_state_data));
83 memset(&this->m_flags, 0,
sizeof(this->m_flags));
101 memset(&this->m_state_data, 0,
sizeof(this->m_state_data));
102 memset(&this->m_flags, 0,
sizeof(this->m_flags));
105 if (this->m_fd.
isOpen()) {
134 &Transaction::r1SubstateRecvEof,
151 this->
rDispatchRecv(buffer, &substate_fns, &Transaction::r1SubstateRecvFileData);
160 &Transaction::r2SubstateRecvEof,
163 &Transaction::r2RecvMd,
175 &Transaction::r2SubstateRecvEof,
177 &Transaction::r2RecvFinAck,
187 &r2_fdir_handlers_normal,
188 &r2_fdir_handlers_normal,
189 &r2_fdir_handlers_finack,
192 this->
rDispatchRecv(buffer, &substate_fns, &Transaction::r2SubstateRecvFileData);
204 if (this->m_ack_timer.
getStatus() == Timer::Status::RUNNING) {
205 this->m_ack_timer.
run();
218 this->m_history->seq_num);
247 if (this->m_inactivity_timer.
getStatus() == Timer::Status::RUNNING) {
248 this->m_inactivity_timer.
run();
250 if (this->m_inactivity_timer.
getStatus() == Timer::Status::EXPIRED) {
257 this->rSendInactivityEvent();
275 this->m_history->peer_eid, this->m_history->seq_num);
284 pending_send =
false;
288 if (!this->rSubstateSendNak()) {
292 if (!this->r2SubstateSendFin()) {
297 pending_send =
false;
306 bool retries_exhausted =
false;
309 this->m_cfdpManager->getPostInactivitySendRetriesParam()) {
310 retries_exhausted =
true;
359 this->m_history->seq_num,
360 this->m_history->fnames.dst_filename);
369 this->m_history->seq_num,
370 this->m_history->fnames.dst_filename, status);
393 (static_cast<U8>(this->m_state_data.receive.r2.eof_cc) !=
411 crc_result = this->m_crc.
getValue();
412 if (crc_result != expected_crc) {
414 this->m_history->seq_num, expected_crc, crc_result);
424 bool send_nak =
false;
425 bool send_fin =
false;
447 if (send_nak && ok_to_send_nak) {
455 this->m_history->seq_num);
496 static_cast<I32>(deserStatus));
512 if ((offset > this->m_fsize) || ((this->m_fsize - offset) < dataSize)) {
514 this->
getClass(), this->m_history->
src_eid, this->m_history->seq_num, offset, dataSize, this->m_fsize);
527 this->m_history->seq_num, offset, status);
541 this->m_history->seq_num, dataSize,
542 static_cast<I32>(write_size));
567 static_cast<I32>(deserStatus));
577 if (!this->m_engine->
recvEof(
this, eof)) {
584 (eof.getFileSize() != this->m_fsize)) {
586 this->m_history->seq_num, this->m_fsize,
595 this->m_engine->
setTxnStatus(
this, static_cast<TxnStatus>(static_cast<I32>(cc)));
602 this->m_history->seq_num);
608 this->m_history->seq_num, static_cast<U8>(cc));
617 void Transaction::r1SubstateRecvEof(
const Fw::Buffer& buffer) {
628 static_cast<I32>(deserStatus));
633 Status::T ret = this->rSubstateRecvEof(buffer);
634 U32 crc = eof.getChecksum();
654 void Transaction::r2SubstateRecvEof(
const Fw::Buffer& buffer) {
668 static_cast<I32>(deserStatus));
673 ret = this->rSubstateRecvEof(buffer);
694 this, static_cast<TxnStatus>(static_cast<I32>(this->m_state_data.
receive.
r2.
eof_cc)));
709 void Transaction::r1SubstateRecvFileData(
const Fw::Buffer& buffer) {
722 static_cast<I32>(deserStatus));
728 ret = this->m_engine->
recvFd(
this, fd);
730 ret = this->rProcessFd(buffer);
735 this->m_crc.
update(fd.getData(), fd.getOffset(),
static_cast<U32
>(fd.getDataSize()));
742 void Transaction::r2SubstateRecvFileData(
const Fw::Buffer& buffer) {
763 static_cast<I32>(deserStatus));
769 ret = this->m_engine->
recvFd(
this, fd);
771 ret = this->rProcessFd(buffer);
776 this->m_chunks->
chunks.
add(fd.getOffset(),
static_cast<FileSize>(fd.getDataSize()));
793 void Transaction::r2GapCompute(
const Chunk* chunk, NakPdu& nak) {
794 FW_ASSERT(chunk->size > 0, static_cast<FwAssertArgType>(chunk->size));
797 FileSize offsetStart = chunk->offset - nak.getScopeStart();
798 FileSize offsetEnd = offsetStart + chunk->size;
801 nak.addSegment(offsetStart, offsetEnd);
804 void Transaction::r2GapComputeWrapper(
const Chunk* chunk,
void* opaque) {
805 struct GapComputeContext {
809 GapComputeContext* ctx =
static_cast<GapComputeContext*
>(opaque);
810 ctx->txn->r2GapCompute(chunk, *ctx->nak);
813 Status::T Transaction::rSubstateSendNak() {
822 nakPdu.initialize(direction,
825 this->m_history->seq_num,
826 this->m_cfdpManager->getLocalEidParam(),
834 U32 gapLimit = (chunkCount < maxChunks) ? maxChunks : (maxChunks - 1);
837 struct GapComputeContext {
840 } gapCtx = {
this, &nakPdu};
842 U32 gapCount = this->m_chunks->
chunks.
computeGaps(static_cast<ChunkIdx>(gapLimit), this->m_fsize, 0,
843 &Transaction::r2GapComputeWrapper, &gapCtx);
851 status = this->m_engine->
sendNak(
this, nakPdu);
860 nakPdu.initialize(direction,
863 this->m_history->seq_num,
864 this->m_cfdpManager->getLocalEidParam(),
870 nakPdu.addSegment(0, 0);
872 status = this->m_engine->
sendNak(
this, nakPdu);
878 Status::T Transaction::r2CalcCrcChunk() {
885 FileSize rx_crc_calc_bytes_per_cycle = 0;
887 memset(buf, 0,
sizeof(buf));
898 if (this->m_fd.
isOpen()) {
921 if (want_offs_size > this->m_fsize) {
924 read_size =
sizeof(buf);
927 if (this->m_state_data.
receive.
cached_pos != this->m_state_data.receive.r2.rx_crc_calc_bytes) {
933 this->m_state_data.receive.r2.rx_crc_calc_bytes, fileStatus);
942 fileStatus = this->m_fd.
read(buf, read_size, Os::File::WaitType::WAIT);
946 static_cast<U32>(expected_read_size), static_cast<I32>(read_size));
952 static_cast<U32>(read_size));
955 count_bytes +=
static_cast<FileSize>(read_size);
989 Status::T Transaction::r2SubstateSendFin() {
995 if (this->r2CalcCrcChunk()) {
1001 sret = this->m_engine->
sendFin(
this, this->m_state_data.
receive.
r2.
dc, this->m_state_data.receive.r2.fs,
1016 void Transaction::r2RecvFinAck(
const Fw::Buffer& buffer) {
1027 static_cast<I32>(deserStatus));
1037 void Transaction::r2RecvMd(
const Fw::Buffer& buffer) {
1041 bool success =
true;
1061 static_cast<I32>(deserStatus));
1066 this->m_engine->
recvMd(
this, md);
1073 this->m_history->seq_num, this->m_fsize,
1074 this->m_state_data.receive.r2.eof_size);
1088 this->
getClass(), this->m_history->
src_eid, this->m_history->seq_num, fname,
1089 this->m_history->fnames.dst_filename, fileSysStatus);
1099 this->m_history->fnames.dst_filename, fileStatus);
1116 void Transaction::rSendInactivityEvent() {
1118 this->m_history->seq_num);
1130 static_cast<U8>(this->m_state_data.receive.sub_state),
1133 selected_handler =
nullptr;
1142 selected_handler = fd_fn;
1153 U8 directiveCodeByte;
1159 if (dispatch->
state[static_cast<U32>(this->m_state_data.receive.sub_state)] !=
nullptr) {
1161 ->fdirective[static_cast<U32>(directiveCode)];
1166 this->
getClass(), this->m_history->
src_eid, this->m_history->seq_num, directiveCodeByte,
1167 static_cast<U8>(this->m_state_data.receive.sub_state));
1176 if (selected_handler !=
nullptr) {
1177 (this->*selected_handler)(buffer);
Status::T recvFd(Transaction *txn, const FileDataPdu &pdu)
Unpack a file data PDU from a received message.
void incrementFaultFileWrite(U8 chanId)
Increment fault file write counter.
Serialization/Deserialization operation was successful.
CfdpTxnFilenames fnames
file names associated with this history entry
TransactionInitType
Transaction initiation method.
#define CFDP_PRI_TRANSACTION_SEQ
Macro type for transaction sequences that is used in printf style formatting.
void incrementRecvErrors(U8 chanId)
Increment receive error counter.
Enum used to determine if a file should be kept or deleted after a CFDP transaction.
A variable-length serializable buffer.
TxnState
High-level state of a transaction.
void log_WARNING_LO_FailAckPduDeserialization(U8 channelId, I32 status) const
Log event FailAckPduDeserialization.
void log_WARNING_LO_FailFileDataPduDeserialization(U8 channelId, I32 status) const
Log event FailFileDataPduDeserialization.
void log_WARNING_LO_RxEofWithError(const Svc::Ccsds::Cfdp::Class &cfdpClass, U32 srcEid, U32 seqNum, U8 conditionCode) const
Log event RxEofWithError.
PlatformSizeType FwSizeType
static Status moveFile(const char *sourcePath, const char *destPath)
Move a file from sourcePath to destPath.
void log_ACTIVITY_LO_RxTempFileCreated(const Svc::Ccsds::Cfdp::Class &cfdpClass, U32 srcEid, U32 seqNum, const Fw::StringBase &filename) const
Log event RxTempFileCreated.
void incrementRecvEofCanceled(U8 chanId)
Increment receive EOF canceled counter.
void rCancel()
Cancel an R transaction.
Fw::SerializeStatus deserializeFrom(Fw::SerialBufferBase &buffer, Fw::Endianness mode=Fw::Endianness::BIG) override
Fw::Serializable interface - deserialize from buffer.
void recvMd(Transaction *txn, const MetadataPdu &pdu)
Handle receipt of metadata PDU.
void r2Reset()
CFDP R2 transaction reset function.
void r2Recv(const Fw::Buffer &buffer)
R2 receive PDU processing.
void log_WARNING_LO_RxAckLimitReached(const Svc::Ccsds::Cfdp::Class &cfdpClass, U32 srcEid, U32 seqNum) const
Log event RxAckLimitReached.
void r2Complete(I32 ok_to_send_nak)
Checks R2 transaction state for transaction completion status.
Receive PDU: Invalid EOF packet.
Transaction initiated via command interface.
void log_WARNING_LO_RxSeekCrcFailed(const Svc::Ccsds::Cfdp::Class &cfdpClass, U32 srcEid, U32 seqNum, U32 offset, I32 status) const
Log event RxSeekCrcFailed.
U8 getNackLimitParam(U8 channelIndex)
const FileDirectiveDispatchTable * state[static_cast< U32 >(RxSubState::RX_SUB_STATE_NUM_STATES)]
void disableTimer(void)
Disables a CFDP timer.
void incrementFaultCrcMismatch(U8 chanId)
Increment fault CRC mismatch counter.
Overwrite file when it exists and creation was requested.
void log_WARNING_LO_RxFileSizeMismatch(const Svc::Ccsds::Cfdp::Class &cfdpClass, U32 srcEid, U32 seqNum, U32 expected, U32 actual) const
Log event RxFileSizeMismatch.
void incrementFaultFileRename(U8 chanId)
Increment fault file rename counter.
void log_WARNING_LO_RxWriteFailed(const Svc::Ccsds::Cfdp::Class &cfdpClass, U32 srcEid, U32 seqNum, U32 expected, I32 actual) const
Log event RxWriteFailed.
CfdpChunkList chunks
Chunk list for gap tracking.
CFDP class 1 - Unreliable transfer (Unacknowledged)
Transaction(Channel *channel, U8 channelId, Engine *engine, CfdpManager *manager)
void addSentNakSegmentRequests(U8 chanId, U32 count)
Add to sent NAK segment requests.
void rTick(I32 *cont)
Perform tick (time-based) processing for R transactions.
U8 post_inactivity_send_retries
terminal-send retries attempted after inactivity fired
Status::T sendAck(Transaction *txn, AckTxnStatus ts, FileDirective dir_code, ConditionCode cc, EntityId peer_eid, TransactionSeq tsn)
Create, encode, and send an ACK (Acknowledgment) PDU.
void incrementRecvDropped(U8 chanId)
Increment receive dropped counter.
TxnStatus
Values for Transaction Status code.
#define CFDP_PRI_ENTITY_ID
Macro type for Entity id that is used in printf style formatting.
void log_WARNING_LO_RxNakLimitReached(const Svc::Ccsds::Cfdp::Class &cfdpClass, U32 srcEid, U32 seqNum) const
Log event RxNakLimitReached.
bool md_recv
md received for r state
SerializeStatus
forward declaration for string
void incrementRecvSpurious(U8 chanId)
Increment receive spurious counter.
void finishTransaction(Transaction *txn, bool keep_history)
Finish a transaction.
Os::FileInterface::Status open(const char *path, Mode mode)
open file with supplied path and mode
State assigned to a transaction after freeing it.
U8 getChannelId() const
Get channel ID.
void incrementFaultFileSeek(U8 chanId)
Increment fault file seek counter.
Class representing a 32-bit checksum as mandated by the CCSDS File Delivery Protocol.
U8 getAckLimitParam(U8 channelIndex)
void add(FileSize offset, FileSize size)
Add a chunk (file segment) to the list.
Status getStatus(void)
Get the status of a CFDP timer.
The type of a File Data PDU.
void r1Reset()
CFDP R1 transaction reset function.
Status::T sendNak(Transaction *txn, NakPdu &nakPdu)
Encode and send a NAK (Negative Acknowledgment) PDU.
void incrementFaultFileOpen(U8 chanId)
Increment fault file open counter.
CfdpFlagsRx rx
applies to only receive file transactions
Status seek(FwSignedSizeType offset, SeekType seekType) override
seek the file pointer to the given offset
FileSize getOffset() const
Get the file offset.
void log_WARNING_LO_RxFileCreateFailed(const Svc::Ccsds::Cfdp::Class &cfdpClass, U32 srcEid, U32 seqNum, const Fw::StringBase &filename, I32 status) const
Log event RxFileCreateFailed.
File will be kept after the CFDP transaction.
void armInactTimer(Transaction *txn)
Arm the inactivity timer for a transaction.
void reset()
Reset transaction to default state.
ConditionCode TxnStatusToConditionCode(TxnStatus txn_stat)
Converts the internal transaction status to a CFDP condition code.
void log_WARNING_LO_RxFileReopenFailed(const Svc::Ccsds::Cfdp::Class &cfdpClass, U32 srcEid, U32 seqNum, const Fw::StringBase &filename, I32 status) const
Log event RxFileReopenFailed.
bool fd_nak_sent
latches that at least one NAK has been sent for file data
State assigned to an unused object on the free list.
U16 getDataSize() const
Get the data size.
void setTxnStatus(Transaction *txn, TxnStatus txn_stat)
Helper function to store transaction status code only.
void close() override
close the file, if not opened then do nothing
Generic CFDP error return code.
void update(const U8 *const data, const U32 offset, const U32 length)
void log_WARNING_LO_FailEofPduDeserialization(U8 channelId, I32 status) const
Log event FailEofPduDeserialization.
Status write(const U8 *buffer, FwSizeType &size)
write data to this file from the supplied buffer bounded by size
void incrementFaultInactivityTimer(U8 chanId)
Increment fault inactivity timer counter.
const char * toChar() const
Convert to a C-style char*.
U32 getValue() const
Get the checksum value.
U32 getRxCrcCalcBytesPerCycleParam(void)
void log_WARNING_LO_RxSeekFailed(const Svc::Ccsds::Cfdp::Class &cfdpClass, U32 srcEid, U32 seqNum, U32 offset, I32 status) const
Log event RxSeekFailed.
FormatStatus format(const CHAR *formatString,...)
write formatted string to buffer
U32 FileSize
File size and offset type.
Receive PDU: EOF file size mismatch.
void rAckTimerTick()
Perform acknowledgement timer tick (time-based) processing for R transactions.
uint8_t U8
8-bit unsigned integer
void log_WARNING_LO_RxEofMdSizeMismatch(const Svc::Ccsds::Cfdp::Class &cfdpClass, U32 srcEid, U32 seqNum, U32 mdSize, U32 eofSize) const
Log event RxEofMdSizeMismatch.
CFDP operation has been successful.
void log_ACTIVITY_HI_RxEofCancelReceived(const Svc::Ccsds::Cfdp::Class &cfdpClass, U32 srcEid, U32 seqNum) const
Log event RxEofCancelReceived.
const U8 * getData() const
Get the data pointer.
Status read(U8 *buffer, FwSizeType &size)
read data from this file into supplied buffer bounded by size
FwSizeType getSize() const
void incrementFaultNakLimit(U8 chanId)
Increment fault NAK limit counter.
void log_WARNING_LO_RxFileRenameFailed(const Svc::Ccsds::Cfdp::Class &cfdpClass, U32 srcEid, U32 seqNum, const Fw::StringBase &tempFile, const Fw::StringBase &finalFile, I32 status) const
Log event RxFileRenameFailed.
Class::T getClass() const
Get transaction class (CLASS_1 or CLASS_2)
A dispatch table for receive file transactions, receive side.
TransactionSeq seq_num
transaction identifier, stays constant for entire transfer
void incrementFaultFileRead(U8 chanId)
Increment fault file read counter.
Operation was successful.
void rInit()
Initialize a transaction structure for R.
void log_WARNING_LO_RxCrcMismatch(const Svc::Ccsds::Cfdp::Class &cfdpClass, U32 srcEid, U32 seqNum, U32 expected, U32 actual) const
Log event RxCrcMismatch.
void log_WARNING_LO_RxFileDataOutOfBounds(const Svc::Ccsds::Cfdp::Class &cfdpClass, U32 srcEid, U32 seqNum, U32 offset, U32 dataSize, U32 fileSize) const
Log event RxFileDataOutOfBounds.
void run(void)
Runs a one second increment of the CFDP timers.
PduTypeEnum::T peekPduType(const Fw::Buffer &buffer)
void incrementFaultRxEofError(U8 chanId)
Increment receive EOF error counter (any condition code that is not no-error or cancel) ...
bool inactivity_fired
set whenever the inactivity timeout expires
RateGroupDivider component implementation.
void log_WARNING_LO_RxInvalidDirectiveCode(const Svc::Ccsds::Cfdp::Class &cfdpClass, U32 srcEid, U32 seqNum, U8 directiveCode, U8 substate) const
Log event RxInvalidDirectiveCode.
ChunkIdx getMaxChunks() const
Get the maximum number of chunks this list can hold.
void rDispatchRecv(const Fw::Buffer &buffer, const RSubstateDispatchTable *dispatch, StateRecvFunc fd_fn)
Dispatch function for received PDUs on receive-file transactions.
CfdpFlagsCommon com
applies to all transactions
void r2SetFinTxnStatus(TxnStatus txn_stat)
Helper function to store transaction status code and set send_fin flag.
TxnStatus txn_stat
final status of operation
Fw::String getTmpDirParam(U8 channelIndex)
Operation was successful.
A table of receive handler functions based on file directive code.
void log_WARNING_LO_RxReadCrcFailed(const Svc::Ccsds::Cfdp::Class &cfdpClass, U32 srcEid, U32 seqNum, U32 expected, I32 actual) const
Log event RxReadCrcFailed.
Status::T rCheckCrc(U32 expected_crc)
Checks that the transaction file's CRC matches expected.
EntityId src_eid
the source eid of the transaction
void log_WARNING_LO_RxInactivityTimeout(const Svc::Ccsds::Cfdp::Class &cfdpClass, U32 srcEid, U32 seqNum) const
Log event RxInactivityTimeout.
Status::T sendFin(Transaction *txn, FinDeliveryCode dc, FinFileStatus fs, ConditionCode cc)
Create, encode, and send a FIN (Finished) PDU.
SerializeStatus setBuffLen(Serializable::SizeType length) override
Set buffer length manually.
void incrementFaultFileSizeMismatch(U8 chanId)
Increment fault file size mismatch counter.
CfdpRxStateData receive
applies to only receive file transactions
U8 eof_cc
remember the cc in the received EOF PDU to echo in eof-ack
void(Transaction::*)(const Fw::Buffer &buffer) StateRecvFunc
A member function pointer for dispatching actions to a handler, with existing PDU data...
void armAckTimer(Transaction *txn)
Arm the ACK timer for a transaction.
ChunkIdx getCount() const
Get the current number of chunks in the list.
void recycleTransaction(Transaction *txn)
Recover resources associated with a transaction.
void incrementFaultAckLimit(U8 chanId)
Increment fault ACK limit counter.
bool isOpen() const
determine if the file is open
bool TxnStatusIsError(TxnStatus txn_stat)
Check if the internal transaction status represents an error.
void r1Recv(const Fw::Buffer &buffer)
R1 receive PDU processing.
FileSize rx_crc_calc_bytes
U32 computeGaps(ChunkIdx maxGaps, FileSize total, FileSize start, GapComputeCallback callback, void *opaque) const
Compute gaps between chunks and invoke callback for each.
EntityId peer_eid
peer_eid is always the "other guy", same src_eid for RX
void log_WARNING_LO_FailMetadataPduDeserialization(U8 channelId, I32 status) const
Log event FailMetadataPduDeserialization.
Status::T recvEof(Transaction *txn, const EofPdu &pdu)
Unpack an EOF PDU from a received message.
void addRecvFileDataBytes(U8 chanId, U32 bytes)
Add to received file data bytes.
Open file for writing and truncates file if it exists, ie same flags as creat()