GCC Code Coverage Report


Directory: ./
File: Svc/FileUplink/FileUplink.cpp
Date: 2026-09-03 21:13:48
Exec Total Coverage
Lines: 122 135 90.4%
Functions: 13 14 92.9%
Branches: 66 81 81.5%

Line Branch Exec Source
1 // ======================================================================
2 // \title FileUplink.cpp
3 // \author bocchino
4 // \brief cpp file for FileUplink component implementation class
5 //
6 // \copyright
7 // Copyright 2009-2016, by the California Institute of Technology.
8 // ALL RIGHTS RESERVED. United States Government Sponsorship
9 // acknowledged.
10 //
11 // ======================================================================
12
13 #include <Fw/Com/ComPacket.hpp>
14 #include <Fw/FPrimeBasicTypes.hpp>
15 #include <Fw/Types/Assert.hpp>
16 #include <Svc/FileUplink/FileUplink.hpp>
17
18 namespace Svc {
19
20 // ----------------------------------------------------------------------
21 // Construction, initialization, and destruction
22 // ----------------------------------------------------------------------
23
24 12 FileUplink::FileUplink(const char* const name)
25 : FileUplinkComponentBase(name),
26 12 m_receiveMode(START),
27 12 m_lastSequenceIndex(0),
28 12 m_lastPacketWriteStatus(Os::File::MAX_STATUS),
29 12 m_filesReceived(this),
30 12 m_filesReceivedFailed(this),
31 12 m_packetsReceived(this),
32
1/1
✓ Branch 10 taken 12 times.
36 m_warnings(this) {}
33
34 24 FileUplink::~FileUplink() {}
35
36 12 void FileUplink::configure(const char* directory) {
37 12 this->m_file.osFile.configure(directory);
38 12 }
39
40 // ----------------------------------------------------------------------
41 // Handler implementations for user-defined typed input ports
42 // ----------------------------------------------------------------------
43
44 27 void FileUplink::bufferSendIn_handler(const FwIndexType portNum, Fw::Buffer& buffer) {
45 // If packet is too small to contain a packet type, log + deallocate and return
46
2/3
✓ Branch 4 taken 27 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 27 times.
27 if (buffer.getSize() < sizeof(FwPacketDescriptorType)) {
47 this->log_WARNING_HI_InvalidPacketReceived(Fw::ComPacketType::FW_PACKET_UNKNOWN);
48 this->bufferSendOut_out(0, buffer);
49 return;
50 }
51
52 // Read the packet type from the packet buffer
53 27 FwPacketDescriptorType packetType = 0;
54
2/2
✓ Branch 2 taken 27 times.
✓ Branch 8 taken 27 times.
27 Fw::SerializeStatus status = buffer.getDeserializer().deserializeTo(packetType);
55 27 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
56
57 // If packet type is not a file packet, log + deallocate and return
58
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (packetType != Fw::ComPacketType::FW_PACKET_FILE) {
59 this->log_WARNING_HI_InvalidPacketReceived(packetType);
60 this->bufferSendOut_out(0, buffer);
61 return;
62 }
63
64 // Deserialize the file packet contents into Fw::FilePacket (remove packet type token)
65
1/1
✓ Branch 4 taken 27 times.
54 Fw::Buffer packetBuffer(buffer.getData() + sizeof(packetType),
66
2/2
✓ Branch 4 taken 27 times.
✓ Branch 9 taken 27 times.
54 buffer.getSize() - static_cast<Fw::Buffer::SizeType>(sizeof(packetType)));
67 27 Fw::FilePacket filePacket;
68
1/1
✓ Branch 1 taken 27 times.
27 status = filePacket.fromBuffer(packetBuffer);
69
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (status != Fw::FW_SERIALIZE_OK) {
70 this->log_WARNING_HI_DecodeError(status);
71 } else {
72
1/1
✓ Branch 1 taken 27 times.
27 Fw::FilePacket::Type header_type = filePacket.asHeader().getType();
73
4/5
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
27 switch (header_type) {
74 11 case Fw::FilePacket::T_START:
75
2/2
✓ Branch 4 taken 11 times.
✓ Branch 7 taken 11 times.
11 this->handleStartPacket(filePacket.asStartPacket());
76 11 break;
77 11 case Fw::FilePacket::T_DATA:
78
2/2
✓ Branch 4 taken 11 times.
✓ Branch 7 taken 11 times.
11 this->handleDataPacket(filePacket.asDataPacket());
79 11 break;
80 3 case Fw::FilePacket::T_END:
81
2/2
✓ Branch 4 taken 3 times.
✓ Branch 7 taken 3 times.
3 this->handleEndPacket(filePacket.asEndPacket());
82 3 break;
83 2 case Fw::FilePacket::T_CANCEL:
84
1/1
✓ Branch 4 taken 2 times.
2 this->handleCancelPacket();
85 2 break;
86 default:
87 FW_ASSERT(false);
88 break;
89 }
90 }
91
1/1
✓ Branch 5 taken 27 times.
27 this->bufferSendOut_out(0, buffer);
92 27 }
93
94 void FileUplink::pingIn_handler(const FwIndexType portNum, U32 key) {
95 // return key
96 this->pingOut_out(0, key);
97 }
98
99 // ----------------------------------------------------------------------
100 // Private helper functions
101 // ----------------------------------------------------------------------
102
103 11 void FileUplink::handleStartPacket(const Fw::FilePacket::StartPacket& startPacket) {
104 // Clear all event throttles in preparation for new start packet
105 11 this->log_WARNING_HI_FileWriteError_ThrottleClear();
106 11 this->log_WARNING_HI_InvalidReceiveMode_ThrottleClear();
107 11 this->log_WARNING_HI_PacketOutOfBounds_ThrottleClear();
108 11 this->log_WARNING_HI_PacketOutOfOrder_ThrottleClear();
109 11 this->m_packetsReceived.packetReceived();
110
3/4
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 10 times.
11 if (this->m_receiveMode != START) {
111 1 this->m_file.osFile.close();
112 1 this->m_warnings.invalidReceiveMode(Fw::FilePacket::T_START);
113 }
114 11 const Os::File::Status status = this->m_file.open(startPacket);
115
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1 times.
11 if (status == Os::File::OP_OK) {
116 10 this->goToDataMode();
117 } else {
118 1 this->m_warnings.fileOpen(this->m_file.name);
119 1 this->goToStartMode();
120 }
121 11 }
122
123 11 void FileUplink::handleDataPacket(const Fw::FilePacket::DataPacket& dataPacket) {
124 11 this->m_packetsReceived.packetReceived();
125
3/4
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 10 times.
11 if (this->m_receiveMode != DATA) {
126 1 this->m_warnings.invalidReceiveMode(Fw::FilePacket::T_DATA);
127 1 return;
128 }
129
130 10 const U32 sequenceIndex = dataPacket.asHeader().getSequenceIndex();
131
132 // skip this packet if it is a duplicate and it has already been written
133
7/8
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 7 times.
✓ Branch 11 taken 1 times.
✓ Branch 12 taken 2 times.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 9 times.
10 if (this->m_lastPacketWriteStatus == Os::File::OP_OK && this->checkDuplicatedPacket(sequenceIndex)) {
134 1 return;
135 }
136
137 9 this->checkSequenceIndex(sequenceIndex);
138 9 const U32 byteOffset = dataPacket.getByteOffset();
139 9 const U32 dataSize = dataPacket.getDataSize();
140
5/6
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 8 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 8 times.
9 if ((std::numeric_limits<U32>::max() - byteOffset < dataSize) || (byteOffset + dataSize > this->m_file.size)) {
141 1 this->m_warnings.packetOutOfBounds(sequenceIndex, this->m_file.name);
142 1 return;
143 }
144 8 FW_ASSERT(dataPacket.getData() != nullptr);
145 8 const Os::File::Status status = this->m_file.write(dataPacket.getData(), byteOffset, dataSize);
146
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if (status != Os::File::OP_OK) {
147 1 this->m_warnings.fileWrite(this->m_file.name);
148 }
149
150 8 this->m_lastPacketWriteStatus = status;
151 }
152
153 3 void FileUplink::handleEndPacket(const Fw::FilePacket::EndPacket& endPacket) {
154 3 this->m_packetsReceived.packetReceived();
155
3/4
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 1 times.
3 if (this->m_receiveMode == DATA) {
156 2 this->checkSequenceIndex(endPacket.asHeader().getSequenceIndex());
157
2/2
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
2 if (this->compareChecksums(endPacket)) {
158 1 this->m_filesReceived.fileReceived();
159 1 this->log_ACTIVITY_HI_FileReceived(this->m_file.name);
160
1/2
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
1 if (this->isConnected_fileAnnounce_OutputPort(0)) {
161 1 this->fileAnnounce_out(0, this->m_file.name);
162 }
163 } else {
164 // compareChecksums() has already issued the BadChecksum warning. The
165 // file failed its integrity check, so it is not announced or reported
166 // as successfully received; record the failed transfer instead.
167 1 this->m_filesReceivedFailed.fileReceivedFailed();
168 }
169 } else {
170 1 this->m_warnings.invalidReceiveMode(Fw::FilePacket::T_END);
171 }
172 3 this->goToStartMode();
173 3 }
174
175 2 void FileUplink::handleCancelPacket() {
176 2 this->m_packetsReceived.packetReceived();
177 2 this->log_ACTIVITY_HI_UplinkCanceled();
178 2 this->goToStartMode();
179 2 }
180
181 11 void FileUplink::checkSequenceIndex(const U32 sequenceIndex) {
182
2/2
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 10 times.
11 if (sequenceIndex != this->m_lastSequenceIndex + 1) {
183 1 this->m_warnings.packetOutOfOrder(sequenceIndex, this->m_lastSequenceIndex);
184 }
185 11 this->m_lastSequenceIndex = sequenceIndex;
186 11 }
187
188 3 bool FileUplink::checkDuplicatedPacket(const U32 sequenceIndex) {
189 // check for duplicate packet
190
2/2
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 2 times.
3 if (sequenceIndex == this->m_lastSequenceIndex) {
191 1 this->m_warnings.packetDuplicate(sequenceIndex);
192 1 return true;
193 }
194
195 2 return false;
196 }
197
198 2 bool FileUplink::compareChecksums(const Fw::FilePacket::EndPacket& endPacket) {
199
1/1
✓ Branch 2 taken 2 times.
2 CFDP::Checksum computed;
200
1/1
✓ Branch 2 taken 2 times.
2 CFDP::Checksum stored;
201
1/1
✓ Branch 4 taken 2 times.
2 this->m_file.getChecksum(computed);
202
1/1
✓ Branch 2 taken 2 times.
2 endPacket.getChecksum(stored);
203
1/1
✓ Branch 1 taken 2 times.
2 const bool match = (computed == stored);
204
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (!match) {
205
3/3
✓ Branch 4 taken 1 times.
✓ Branch 7 taken 1 times.
✓ Branch 10 taken 1 times.
1 this->m_warnings.badChecksum(computed.getValue(), stored.getValue());
206 }
207 2 return match;
208 2 }
209
210 6 void FileUplink::goToStartMode() {
211 6 this->m_file.osFile.close();
212 6 this->m_receiveMode = START;
213 6 this->m_lastSequenceIndex = 0;
214 6 this->m_lastPacketWriteStatus = Os::File::MAX_STATUS;
215 6 }
216
217 10 void FileUplink::goToDataMode() {
218 10 this->m_receiveMode = DATA;
219 10 this->m_lastSequenceIndex = 0;
220 10 this->m_lastPacketWriteStatus = Os::File::MAX_STATUS;
221 10 }
222
223 } // namespace Svc
224