GCC Code Coverage Report


Directory: ./
File: Utils.cpp
Date: 2026-09-03 22:13:22
Exec Total Coverage
Lines: 0 50 0.0%
Functions: 0 7 0.0%
Branches: 0 18 0.0%

Line Branch Exec Source
1 // ======================================================================
2 // \title Utils.cpp
3 // \brief CFDP utility functions
4 //
5 // This file is a port of the cf_utils.c file from the
6 // NASA Core Flight System (cFS) CFDP (CF) Application,
7 // version 3.0.0, adapted for use within the F-Prime (F') framework.
8 //
9 // The CFDP general utility functions source file
10 //
11 // Various odds and ends are put here.
12 //
13 // ======================================================================
14 //
15 // NASA Docket No. GSC-18,447-1
16 //
17 // Copyright (c) 2019 United States Government as represented by the
18 // Administrator of the National Aeronautics and Space Administration.
19 // All Rights Reserved.
20 //
21 // Licensed under the Apache License, Version 2.0 (the "License"); you may
22 // not use this file except in compliance with the License. You may obtain
23 // a copy of the License at
24 //
25 // http://www.apache.org/licenses/LICENSE-2.0
26 //
27 // Unless required by applicable law or agreed to in writing, software
28 // distributed under the License is distributed on an "AS IS" BASIS,
29 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
30 // See the License for the specific language governing permissions and
31 // limitations under the License.
32 //
33 // ======================================================================
34
35 #include <Svc/Ccsds/CfdpManager/Clist.hpp>
36 #include <Svc/Ccsds/CfdpManager/Engine.hpp>
37 #include <Svc/Ccsds/CfdpManager/Utils.hpp>
38
39 namespace Svc {
40 namespace Ccsds {
41 namespace Cfdp {
42
43 AckTxnStatus GetTxnStatus(Transaction* txn) {
44 AckTxnStatus LocalStatus;
45
46 // check if this is still an active Tx (not in holdover or drop etc)
47 // in theory this should never be called on S1 because there is no fin-ack to send,
48 // but including it for completeness (because it is an active txn)
49 if (txn == nullptr) {
50 LocalStatus = AckTxnStatus::ACK_TXN_STATUS_UNRECOGNIZED;
51 } else
52 switch (txn->getState()) {
53 case TxnState::TXN_STATE_S1:
54 case TxnState::TXN_STATE_R1:
55 case TxnState::TXN_STATE_S2:
56 case TxnState::TXN_STATE_R2:
57 LocalStatus = AckTxnStatus::ACK_TXN_STATUS_ACTIVE;
58 break;
59
60 case TxnState::TXN_STATE_DROP:
61 case TxnState::TXN_STATE_HOLD:
62 LocalStatus = AckTxnStatus::ACK_TXN_STATUS_TERMINATED;
63 break;
64
65 default:
66 LocalStatus = AckTxnStatus::ACK_TXN_STATUS_INVALID;
67 break;
68 }
69
70 return LocalStatus;
71 }
72
73 // Static member function - can access private members
74 CListTraverseStatus Transaction::findBySequenceNumberCallback(CListNode* node, void* context) {
75 Transaction* txn = container_of_cpp(node, &Transaction::m_cl_node);
76 CListTraverseStatus ret = CLIST_TRAVERSE_CONTINUE;
77 CfdpTraverseTransSeqArg* seqContext = static_cast<CfdpTraverseTransSeqArg*>(context);
78
79 if (txn->m_history && (txn->m_history->src_eid == seqContext->src_eid) &&
80 (txn->m_history->seq_num == seqContext->transaction_sequence_number)) {
81 seqContext->txn = txn;
82 ret = CLIST_TRAVERSE_EXIT; // exit early
83 }
84
85 return ret;
86 }
87
88 // Static member function - can access private members
89 CListTraverseStatus Transaction::prioritySearchCallback(CListNode* node, void* context) {
90 Transaction* txn = container_of_cpp(node, &Transaction::m_cl_node);
91 CfdpTraversePriorityArg* arg = static_cast<CfdpTraversePriorityArg*>(context);
92
93 if (txn->m_priority <= arg->priority) {
94 // found it!
95 //
96 // the current transaction's prio is less than desired (higher)
97 arg->txn = txn;
98 return CLIST_TRAVERSE_EXIT;
99 }
100
101 return CLIST_TRAVERSE_CONTINUE;
102 }
103
104 // Legacy wrappers for backward compatibility
105 CListTraverseStatus FindTransactionBySequenceNumberImpl(CListNode* node, void* context) {
106 return Transaction::findBySequenceNumberCallback(node, context);
107 }
108
109 CListTraverseStatus PrioSearch(CListNode* node, void* context) {
110 return Transaction::prioritySearchCallback(node, context);
111 }
112
113 bool TxnStatusIsError(TxnStatus txn_stat) {
114 // The value of TxnStatus::TXN_STATUS_UNDEFINED (-1) indicates a transaction is in progress and no error
115 // has occurred yet. This will be set to TxnStatus::TXN_STATUS_NO_ERROR (0) after successful completion
116 // of the transaction (FIN/EOF). Anything else indicates a problem has occurred.
117 return (txn_stat > TxnStatus::TXN_STATUS_NO_ERROR);
118 }
119
120 ConditionCode TxnStatusToConditionCode(TxnStatus txn_stat) {
121 ConditionCode result;
122
123 if (!TxnStatusIsError(txn_stat)) {
124 // If no status has been set (TxnStatus::TXN_STATUS_UNDEFINED), treat that as NO_ERROR for
125 // the purpose of CFDP CC. This can occur e.g. when sending ACK PDUs and no errors
126 // have happened yet, but the transaction is not yet complete and thus not final.
127 result = ConditionCode::CONDITION_CODE_NO_ERROR;
128 } else {
129 switch (txn_stat) {
130 // The definition of TxnStatus is such that the 4-bit codes (0-15) share the same
131 // numeric values as the CFDP condition codes, and can be put directly into the 4-bit
132 // CC field of a FIN/ACK/EOF PDU. Extended codes use the upper bits (>15) to differentiate
133 case TxnStatus::TXN_STATUS_NO_ERROR:
134 case TxnStatus::TXN_STATUS_POS_ACK_LIMIT_REACHED:
135 case TxnStatus::TXN_STATUS_KEEP_ALIVE_LIMIT_REACHED:
136 case TxnStatus::TXN_STATUS_INVALID_TRANSMISSION_MODE:
137 case TxnStatus::TXN_STATUS_FILESTORE_REJECTION:
138 case TxnStatus::TXN_STATUS_FILE_CHECKSUM_FAILURE:
139 case TxnStatus::TXN_STATUS_FILE_SIZE_ERROR:
140 case TxnStatus::TXN_STATUS_NAK_LIMIT_REACHED:
141 case TxnStatus::TXN_STATUS_INACTIVITY_DETECTED:
142 case TxnStatus::TXN_STATUS_INVALID_FILE_STRUCTURE:
143 case TxnStatus::TXN_STATUS_CHECK_LIMIT_REACHED:
144 case TxnStatus::TXN_STATUS_UNSUPPORTED_CHECKSUM_TYPE:
145 case TxnStatus::TXN_STATUS_SUSPEND_REQUEST_RECEIVED:
146 case TxnStatus::TXN_STATUS_CANCEL_REQUEST_RECEIVED:
147 result = static_cast<ConditionCode>(txn_stat);
148 break;
149
150 // Extended status codes below here ---
151 // There are no CFDP CCs to directly represent these status codes. Normally this should
152 // not happen as the engine should not be sending a CFDP CC (FIN/ACK/EOF PDU) for a
153 // transaction that is not in a valid CFDP-defined state. This should be translated
154 // to the closest CFDP CC per the intent/meaning of the transaction status code.
155
156 case TxnStatus::TXN_STATUS_ACK_LIMIT_NO_FIN:
157 case TxnStatus::TXN_STATUS_ACK_LIMIT_NO_EOF:
158 // this is similar to the inactivity timeout (no fin-ack)
159 result = ConditionCode::CONDITION_CODE_INACTIVITY_DETECTED;
160 break;
161
162 default:
163 // Catch-all: any invalid protocol state will cancel the transaction, and thus this
164 // is the closest CFDP CC in practice for all other unhandled errors.
165 result = ConditionCode::CONDITION_CODE_CANCEL_REQUEST_RECEIVED;
166 break;
167 }
168 }
169
170 return result;
171 }
172
173 } // namespace Cfdp
174 } // namespace Ccsds
175 } // namespace Svc
176