62 m_txn_class(Cfdp::
Class::CLASS_1),
71 m_keep(Cfdp::
Keep::KEEP),
72 m_chan_num(channelId),
79 m_cfdpManager(manager),
84 memset(&this->m_state_data, 0,
sizeof(this->m_state_data));
85 memset(&this->m_flags, 0,
sizeof(this->m_flags));
100 this->m_pb =
nullptr;
103 memset(&this->m_state_data, 0,
sizeof(this->m_state_data));
104 memset(&this->m_flags, 0,
sizeof(this->m_flags));
107 if (this->m_fd.
isOpen()) {
136 &Transaction::r1SubstateRecvEof,
153 this->
rDispatchRecv(buffer, &substate_fns, &Transaction::r1SubstateRecvFileData);
162 &Transaction::r2SubstateRecvEof,
165 &Transaction::r2RecvMd,
177 &Transaction::r2SubstateRecvEof,
179 &Transaction::r2RecvFinAck,
189 &r2_fdir_handlers_normal,
190 &r2_fdir_handlers_normal,
191 &r2_fdir_handlers_finack,
194 this->
rDispatchRecv(buffer, &substate_fns, &Transaction::r2SubstateRecvFileData);
206 if (this->m_ack_timer.
getStatus() == Timer::Status::RUNNING) {
207 this->m_ack_timer.
run();
220 this->m_history->seq_num);
249 if (this->m_inactivity_timer.
getStatus() == Timer::Status::RUNNING) {
250 this->m_inactivity_timer.
run();
252 if (this->m_inactivity_timer.
getStatus() == Timer::Status::EXPIRED) {
259 this->rSendInactivityEvent();
277 this->m_history->peer_eid, this->m_history->seq_num);
286 pending_send =
false;
290 if (!this->rSubstateSendNak()) {
294 if (!this->r2SubstateSendFin()) {
299 pending_send =
false;
308 bool retries_exhausted =
false;
311 this->m_cfdpManager->getPostInactivitySendRetriesParam()) {
312 retries_exhausted =
true;
361 this->m_history->seq_num,
362 this->m_history->fnames.dst_filename);
371 this->m_history->seq_num,
372 this->m_history->fnames.dst_filename, status);
395 (static_cast<U8>(this->m_state_data.receive.r2.eof_cc) !=
413 crc_result = this->m_crc.
getValue();
414 if (crc_result != expected_crc) {
416 this->m_history->seq_num, expected_crc, crc_result);
426 bool send_nak =
false;
427 bool send_fin =
false;
449 if (send_nak && ok_to_send_nak) {
457 this->m_history->seq_num);
498 static_cast<I32>(deserStatus));
515 const FileSize bound = this->m_flags.
rx.
md_recv ? this->m_fsize : std::numeric_limits<FileSize>::max();
516 if ((offset > bound) || ((bound - offset) < dataSize)) {
518 this->
getClass(), this->m_history->
src_eid, this->m_history->seq_num, offset, dataSize, bound);
539 this->m_history->seq_num, offset, status);
553 this->m_history->seq_num, dataSize,
554 static_cast<I32>(write_size));
579 static_cast<I32>(deserStatus));
589 if (!this->m_engine->
recvEof(
this, eof)) {
596 (eof.getFileSize() != this->m_fsize)) {
598 this->m_history->seq_num, this->m_fsize,
607 this->m_engine->
setTxnStatus(
this, static_cast<TxnStatus>(static_cast<I32>(cc)));
614 this->m_history->seq_num);
620 this->m_history->seq_num, static_cast<U8>(cc));
629 void Transaction::r1SubstateRecvEof(
const Fw::Buffer& buffer) {
640 static_cast<I32>(deserStatus));
645 Status::T ret = this->rSubstateRecvEof(buffer);
646 U32 crc = eof.getChecksum();
666 void Transaction::r2SubstateRecvEof(
const Fw::Buffer& buffer) {
680 static_cast<I32>(deserStatus));
685 ret = this->rSubstateRecvEof(buffer);
706 this, static_cast<TxnStatus>(static_cast<I32>(this->m_state_data.
receive.
r2.
eof_cc)));
721 void Transaction::r1SubstateRecvFileData(
const Fw::Buffer& buffer) {
734 static_cast<I32>(deserStatus));
740 ret = this->m_engine->
recvFd(
this, fd);
742 ret = this->rProcessFd(buffer);
747 this->m_crc.
update(fd.getData(), fd.getOffset(),
static_cast<U32
>(fd.getDataSize()));
754 void Transaction::r2SubstateRecvFileData(
const Fw::Buffer& buffer) {
775 static_cast<I32>(deserStatus));
781 ret = this->m_engine->
recvFd(
this, fd);
783 ret = this->rProcessFd(buffer);
788 this->m_chunks->
chunks.
add(fd.getOffset(),
static_cast<FileSize>(fd.getDataSize()));
805 void Transaction::r2GapCompute(
const Chunk* chunk, NakPdu& nak) {
806 FW_ASSERT(chunk->size > 0, static_cast<FwAssertArgType>(chunk->size));
809 FileSize offsetStart = chunk->offset - nak.getScopeStart();
810 FileSize offsetEnd = offsetStart + chunk->size;
813 nak.addSegment(offsetStart, offsetEnd);
816 void Transaction::r2GapComputeWrapper(
const Chunk* chunk,
void* opaque) {
817 struct GapComputeContext {
821 GapComputeContext* ctx =
static_cast<GapComputeContext*
>(opaque);
822 ctx->txn->r2GapCompute(chunk, *ctx->nak);
825 Status::T Transaction::rSubstateSendNak() {
834 nakPdu.initialize(direction,
837 this->m_history->seq_num,
838 this->m_cfdpManager->getLocalEidParam(),
846 U32 gapLimit = (chunkCount < maxChunks) ? maxChunks : (maxChunks - 1);
849 struct GapComputeContext {
852 } gapCtx = {
this, &nakPdu};
854 U32 gapCount = this->m_chunks->
chunks.
computeGaps(static_cast<ChunkIdx>(gapLimit), this->m_fsize, 0,
855 &Transaction::r2GapComputeWrapper, &gapCtx);
863 status = this->m_engine->
sendNak(
this, nakPdu);
872 nakPdu.initialize(direction,
875 this->m_history->seq_num,
876 this->m_cfdpManager->getLocalEidParam(),
882 nakPdu.addSegment(0, 0);
884 status = this->m_engine->
sendNak(
this, nakPdu);
890 Status::T Transaction::r2CalcCrcChunk() {
897 FileSize rx_crc_calc_bytes_per_cycle = 0;
899 memset(buf, 0,
sizeof(buf));
910 if (this->m_fd.
isOpen()) {
933 if (want_offs_size > this->m_fsize) {
936 read_size =
sizeof(buf);
939 if (this->m_state_data.
receive.
cached_pos != this->m_state_data.receive.r2.rx_crc_calc_bytes) {
945 this->m_state_data.receive.r2.rx_crc_calc_bytes, fileStatus);
954 fileStatus = this->m_fd.
read(buf, read_size, Os::File::WaitType::WAIT);
958 static_cast<U32>(expected_read_size), static_cast<I32>(read_size));
964 static_cast<U32>(read_size));
967 count_bytes +=
static_cast<FileSize>(read_size);
1001 Status::T Transaction::r2SubstateSendFin() {
1007 if (this->r2CalcCrcChunk()) {
1013 sret = this->m_engine->
sendFin(
this, this->m_state_data.
receive.
r2.
dc, this->m_state_data.receive.r2.fs,
1028 void Transaction::r2RecvFinAck(
const Fw::Buffer& buffer) {
1039 static_cast<I32>(deserStatus));
1049 void Transaction::r2RecvMd(
const Fw::Buffer& buffer) {
1053 bool success =
true;
1073 static_cast<I32>(deserStatus));
1078 this->m_engine->
recvMd(
this, md);
1085 this->m_history->seq_num, this->m_fsize,
1086 this->m_state_data.receive.r2.eof_size);
1100 this->
getClass(), this->m_history->
src_eid, this->m_history->seq_num, fname,
1101 this->m_history->fnames.dst_filename, fileSysStatus);
1111 this->m_history->fnames.dst_filename, fileStatus);
1128 void Transaction::rSendInactivityEvent() {
1130 this->m_history->seq_num);
1142 static_cast<U8>(this->m_state_data.receive.sub_state),
1145 selected_handler =
nullptr;
1154 selected_handler = fd_fn;
1165 U8 directiveCodeByte;
1171 if (dispatch->
state[static_cast<U32>(this->m_state_data.receive.sub_state)] !=
nullptr) {
1173 ->fdirective[static_cast<U32>(directiveCode)];
1178 this->
getClass(), this->m_history->
src_eid, this->m_history->seq_num, directiveCodeByte,
1179 static_cast<U8>(this->m_state_data.receive.sub_state));
1188 if (selected_handler !=
nullptr) {
1189 (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.
SerializeStatus setBuffLen(Serializable::SizeType length) override
Set buffer length manually.
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.
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()