GCC Code Coverage Report


Directory: Svc/Ccsds/CfdpManager/
File: Utils.cpp
Date: 2026-09-03 21:16:27
Exec Total Coverage
Lines: 46 50 92.0%
Functions: 5 7 71.4%
Branches: 16 18 88.9%

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 229 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
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 228 times.
229 if (txn == nullptr) {
50 1 LocalStatus = AckTxnStatus::ACK_TXN_STATUS_UNRECOGNIZED;
51 } else
52
3/3
✓ Branch 2 taken 155 times.
✓ Branch 3 taken 72 times.
✓ Branch 4 taken 1 times.
228 switch (txn->getState()) {
53 155 case TxnState::TXN_STATE_S1:
54 case TxnState::TXN_STATE_R1:
55 case TxnState::TXN_STATE_S2:
56 case TxnState::TXN_STATE_R2:
57 155 LocalStatus = AckTxnStatus::ACK_TXN_STATUS_ACTIVE;
58 155 break;
59
60 72 case TxnState::TXN_STATE_DROP:
61 case TxnState::TXN_STATE_HOLD:
62 72 LocalStatus = AckTxnStatus::ACK_TXN_STATUS_TERMINATED;
63 72 break;
64
65 1 default:
66 1 LocalStatus = AckTxnStatus::ACK_TXN_STATUS_INVALID;
67 1 break;
68 }
69
70 229 return LocalStatus;
71 }
72
73 // Static member function - can access private members
74 1343 CListTraverseStatus Transaction::findBySequenceNumberCallback(CListNode* node, void* context) {
75 1343 Transaction* txn = container_of_cpp(node, &Transaction::m_cl_node);
76 1343 CListTraverseStatus ret = CLIST_TRAVERSE_CONTINUE;
77 1343 CfdpTraverseTransSeqArg* seqContext = static_cast<CfdpTraverseTransSeqArg*>(context);
78
79
2/4
✓ Branch 2 taken 1343 times.
✗ Branch 3 not taken.
✓ Branch 10 taken 1343 times.
✗ Branch 11 not taken.
1343 if (txn->m_history && (txn->m_history->src_eid == seqContext->src_eid) &&
80
2/2
✓ Branch 5 taken 67 times.
✓ Branch 6 taken 1276 times.
1343 (txn->m_history->seq_num == seqContext->transaction_sequence_number)) {
81 67 seqContext->txn = txn;
82 67 ret = CLIST_TRAVERSE_EXIT; // exit early
83 }
84
85 1343 return ret;
86 }
87
88 // Static member function - can access private members
89 2 CListTraverseStatus Transaction::prioritySearchCallback(CListNode* node, void* context) {
90 2 Transaction* txn = container_of_cpp(node, &Transaction::m_cl_node);
91 2 CfdpTraversePriorityArg* arg = static_cast<CfdpTraversePriorityArg*>(context);
92
93
2/2
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
2 if (txn->m_priority <= arg->priority) {
94 // found it!
95 //
96 // the current transaction's prio is less than desired (higher)
97 1 arg->txn = txn;
98 1 return CLIST_TRAVERSE_EXIT;
99 }
100
101 1 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 193 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 193 return (txn_stat > TxnStatus::TXN_STATUS_NO_ERROR);
118 }
119
120 48 ConditionCode TxnStatusToConditionCode(TxnStatus txn_stat) {
121 ConditionCode result;
122
123
2/2
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 26 times.
48 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 22 result = ConditionCode::CONDITION_CODE_NO_ERROR;
128 } else {
129
3/3
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 3 times.
26 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 21 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 21 result = static_cast<ConditionCode>(txn_stat);
148 21 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 2 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 2 result = ConditionCode::CONDITION_CODE_INACTIVITY_DETECTED;
160 2 break;
161
162 3 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 3 result = ConditionCode::CONDITION_CODE_CANCEL_REQUEST_RECEIVED;
166 3 break;
167 }
168 }
169
170 48 return result;
171 }
172
173 } // namespace Cfdp
174 } // namespace Ccsds
175 } // namespace Svc
176