F´ Flight Software - C/C++ Documentation
A framework for building embedded system applications to NASA flight quality standards.
FileUplink.cpp
Go to the documentation of this file.
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>
17 
18 namespace Svc {
19 
20 // ----------------------------------------------------------------------
21 // Construction, initialization, and destruction
22 // ----------------------------------------------------------------------
23 
24 FileUplink::FileUplink(const char* const name)
26  m_receiveMode(START),
27  m_lastSequenceIndex(0),
28  m_lastPacketWriteStatus(Os::File::MAX_STATUS),
29  m_filesReceived(this),
30  m_filesReceivedFailed(this),
31  m_packetsReceived(this),
32  m_warnings(this) {}
33 
35 
36 void FileUplink::configure(const char* directory) {
37  this->m_file.osFile.configure(directory);
38 }
39 
40 // ----------------------------------------------------------------------
41 // Handler implementations for user-defined typed input ports
42 // ----------------------------------------------------------------------
43 
44 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  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  FwPacketDescriptorType packetType = 0;
54  Fw::SerializeStatus status = buffer.getDeserializer().deserializeTo(packetType);
55  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
56 
57  // If packet type is not a file packet, log + deallocate and return
58  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  Fw::Buffer packetBuffer(buffer.getData() + sizeof(packetType),
66  buffer.getSize() - static_cast<Fw::Buffer::SizeType>(sizeof(packetType)));
67  Fw::FilePacket filePacket;
68  status = filePacket.fromBuffer(packetBuffer);
69  if (status != Fw::FW_SERIALIZE_OK) {
70  this->log_WARNING_HI_DecodeError(status);
71  } else {
72  Fw::FilePacket::Type header_type = filePacket.asHeader().getType();
73  switch (header_type) {
75  this->handleStartPacket(filePacket.asStartPacket());
76  break;
78  this->handleDataPacket(filePacket.asDataPacket());
79  break;
81  this->handleEndPacket(filePacket.asEndPacket());
82  break;
84  this->handleCancelPacket();
85  break;
86  default:
87  FW_ASSERT(false);
88  break;
89  }
90  }
91  this->bufferSendOut_out(0, buffer);
92 }
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 void FileUplink::handleStartPacket(const Fw::FilePacket::StartPacket& startPacket) {
104  // Clear all event throttles in preparation for new start packet
109  this->m_packetsReceived.packetReceived();
110  if (this->m_receiveMode != START) {
111  this->m_file.osFile.close();
112  this->m_warnings.invalidReceiveMode(Fw::FilePacket::T_START);
113  }
114  const Os::File::Status status = this->m_file.open(startPacket);
115  if (status == Os::File::OP_OK) {
116  this->goToDataMode();
117  } else {
118  this->m_warnings.fileOpen(this->m_file.name);
119  this->goToStartMode();
120  }
121 }
122 
123 void FileUplink::handleDataPacket(const Fw::FilePacket::DataPacket& dataPacket) {
124  this->m_packetsReceived.packetReceived();
125  if (this->m_receiveMode != DATA) {
126  this->m_warnings.invalidReceiveMode(Fw::FilePacket::T_DATA);
127  return;
128  }
129 
130  const U32 sequenceIndex = dataPacket.asHeader().getSequenceIndex();
131 
132  // skip this packet if it is a duplicate and it has already been written
133  if (this->m_lastPacketWriteStatus == Os::File::OP_OK && this->checkDuplicatedPacket(sequenceIndex)) {
134  return;
135  }
136 
137  this->checkSequenceIndex(sequenceIndex);
138  const U32 byteOffset = dataPacket.getByteOffset();
139  const U32 dataSize = dataPacket.getDataSize();
140  if ((std::numeric_limits<U32>::max() - byteOffset < dataSize) || (byteOffset + dataSize > this->m_file.size)) {
141  this->m_warnings.packetOutOfBounds(sequenceIndex, this->m_file.name);
142  return;
143  }
144  FW_ASSERT(dataPacket.getData() != nullptr);
145  const Os::File::Status status = this->m_file.write(dataPacket.getData(), byteOffset, dataSize);
146  if (status != Os::File::OP_OK) {
147  this->m_warnings.fileWrite(this->m_file.name);
148  }
149 
150  this->m_lastPacketWriteStatus = status;
151 }
152 
153 void FileUplink::handleEndPacket(const Fw::FilePacket::EndPacket& endPacket) {
154  this->m_packetsReceived.packetReceived();
155  if (this->m_receiveMode == DATA) {
156  this->checkSequenceIndex(endPacket.asHeader().getSequenceIndex());
157  if (this->compareChecksums(endPacket)) {
158  this->m_filesReceived.fileReceived();
159  this->log_ACTIVITY_HI_FileReceived(this->m_file.name);
161  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  this->m_filesReceivedFailed.fileReceivedFailed();
168  }
169  } else {
170  this->m_warnings.invalidReceiveMode(Fw::FilePacket::T_END);
171  }
172  this->goToStartMode();
173 }
174 
175 void FileUplink::handleCancelPacket() {
176  this->m_packetsReceived.packetReceived();
178  this->goToStartMode();
179 }
180 
181 void FileUplink::checkSequenceIndex(const U32 sequenceIndex) {
182  if (sequenceIndex != this->m_lastSequenceIndex + 1) {
183  this->m_warnings.packetOutOfOrder(sequenceIndex, this->m_lastSequenceIndex);
184  }
185  this->m_lastSequenceIndex = sequenceIndex;
186 }
187 
188 bool FileUplink::checkDuplicatedPacket(const U32 sequenceIndex) {
189  // check for duplicate packet
190  if (sequenceIndex == this->m_lastSequenceIndex) {
191  this->m_warnings.packetDuplicate(sequenceIndex);
192  return true;
193  }
194 
195  return false;
196 }
197 
198 bool FileUplink::compareChecksums(const Fw::FilePacket::EndPacket& endPacket) {
199  CFDP::Checksum computed;
200  CFDP::Checksum stored;
201  this->m_file.getChecksum(computed);
202  endPacket.getChecksum(stored);
203  const bool match = (computed == stored);
204  if (!match) {
205  this->m_warnings.badChecksum(computed.getValue(), stored.getValue());
206  }
207  return match;
208 }
209 
210 void FileUplink::goToStartMode() {
211  this->m_file.osFile.close();
212  this->m_receiveMode = START;
213  this->m_lastSequenceIndex = 0;
214  this->m_lastPacketWriteStatus = Os::File::MAX_STATUS;
215 }
216 
217 void FileUplink::goToDataMode() {
218  this->m_receiveMode = DATA;
219  this->m_lastSequenceIndex = 0;
220  this->m_lastPacketWriteStatus = Os::File::MAX_STATUS;
221 }
222 
223 } // namespace Svc
const U8 * getData() const
Get the data.
Definition: FilePacket.hpp:216
Serialization/Deserialization operation was successful.
U16 FwPacketDescriptorType
The width of packet descriptors when they are serialized by the framework.
const FilePacket::Header & asHeader() const
Get this as a Header.
Definition: FilePacket.hpp:207
SerializeStatus deserializeTo(U8 &val, Endianness mode=Endianness::BIG) override
Deserialize an 8-bit unsigned integer value.
U32 getByteOffset() const
Get the byte offset.
Definition: FilePacket.hpp:210
const FilePacket::Header & asHeader() const
Get this as a Header.
Definition: FilePacket.hpp:253
The type of a data packet.
Definition: FilePacket.hpp:171
U8 * getData() const
Definition: Buffer.cpp:82
void getChecksum(CFDP::Checksum &checksum) const
Get the checksum.
Definition: EndPacket.cpp:38
Type
Packet type.
Definition: FilePacket.hpp:40
U32 getDataSize() const
Get the data size.
Definition: FilePacket.hpp:213
Maximum value of status.
Definition: File.hpp:55
SerializeStatus
forward declaration for string
ExternalSerializeBufferWithMemberCopy getDeserializer()
Definition: Buffer.cpp:165
Class representing a 32-bit checksum as mandated by the CCSDS File Delivery Protocol.
Definition: Checksum.hpp:53
The type of a start packet.
Definition: FilePacket.hpp:121
U32 getValue() const
Get the checksum value.
Definition: Checksum.cpp:45
FwSizeType getSize() const
Definition: Buffer.cpp:90
SerializeStatus fromBuffer(const Buffer &buffer)
Definition: FilePacket.cpp:22
Operation was successful.
Definition: File.hpp:42
PlatformIndexType FwIndexType
FwSizeType SizeType
The size type for a buffer - for backwards compatibility.
Definition: Buffer.hpp:67
RateGroupDivider component implementation.
A file packet.
Definition: FilePacket.hpp:33
U32 getSequenceIndex(void) const
Definition: FilePacket.hpp:117
#define FW_ASSERT(...)
Definition: Assert.hpp:14
The type of an end packet.
Definition: FilePacket.hpp:230