F´ Flight Software - C/C++ Documentation  devel
A framework for building embedded system applications to NASA flight quality standards.
FprimeProtocol.cpp
Go to the documentation of this file.
1 // ======================================================================
2 // \title FprimeProtocol.cpp
3 // \author mstarch
4 // \brief cpp file for FprimeProtocol class
5 //
6 // \copyright
7 // Copyright 2009-2022, by the California Institute of Technology.
8 // ALL RIGHTS RESERVED. United States Government Sponsorship
9 // acknowledged.
10 //
11 // ======================================================================
12 #include "FprimeProtocol.hpp"
13 #include "FpConfig.hpp"
14 #include "Utils/Hash/Hash.hpp"
15 
16 namespace Svc {
17 
19 
21 
22 void FprimeFraming::frame(const U8* const data, const U32 size, Fw::ComPacket::ComPacketType packet_type) {
23  FW_ASSERT(data != nullptr);
24  FW_ASSERT(m_interface != nullptr);
25  // Use of I32 size is explicit as ComPacketType will be specifically serialized as an I32
26  FpFrameHeader::TokenType real_data_size =
27  size + ((packet_type != Fw::ComPacket::FW_PACKET_UNKNOWN) ?
28  static_cast<Svc::FpFrameHeader::TokenType>(sizeof(I32)) :
29  0);
31  Fw::Buffer buffer = m_interface->allocate(total);
32  Fw::SerializeBufferBase& serializer = buffer.getSerializeRepr();
33  Utils::HashBuffer hash;
34 
35  // Serialize data
36  Fw::SerializeStatus status;
37  status = serializer.serialize(FpFrameHeader::START_WORD);
38  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
39 
40  status = serializer.serialize(real_data_size);
41  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
42 
43  // Serialize packet type if supplied, otherwise it *must* be present in the data
44  if (packet_type != Fw::ComPacket::FW_PACKET_UNKNOWN) {
45  status = serializer.serialize(static_cast<I32>(packet_type)); // I32 used for enum storage
46  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
47  }
48 
49  status = serializer.serialize(data, size, true); // Serialize without length
50  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
51 
52  // Calculate and add transmission hash
53  Utils::Hash::hash(buffer.getData(), static_cast<NATIVE_INT_TYPE>(total - HASH_DIGEST_LENGTH), hash);
54  status = serializer.serialize(hash.getBuffAddr(), HASH_DIGEST_LENGTH, true);
55  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
56 
57  buffer.setSize(total);
58 
59  m_interface->send(buffer);
60 }
61 
63  Utils::Hash hash;
64  Utils::HashBuffer hashBuffer;
65  // Initialize the checksum and loop through all bytes calculating it
66  hash.init();
67  for (U32 i = 0; i < size; i++) {
68  U8 byte;
69  const Fw::SerializeStatus status = ring.peek(byte, i);
70  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
71  hash.update(&byte, 1);
72  }
73  hash.final(hashBuffer);
74  // Now loop through the hash digest bytes and check for equality
75  for (U32 i = 0; i < HASH_DIGEST_LENGTH; i++) {
76  U8 calc = static_cast<U8>(hashBuffer.getBuffAddr()[i]);
77  U8 sent = 0;
78  const Fw::SerializeStatus status = ring.peek(sent, size + i);
79  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
80  if (calc != sent) {
81  return false;
82  }
83  }
84  return true;
85 }
86 
88  FpFrameHeader::TokenType start = 0;
89  FpFrameHeader::TokenType size = 0;
90  FW_ASSERT(m_interface != nullptr);
91  // Check for header or ask for more data
93  needed = FpFrameHeader::SIZE;
95  }
96  // Read start value from header
97  Fw::SerializeStatus status = ring.peek(start, 0);
98  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
99  if (start != FpFrameHeader::START_WORD) {
100  // Start word must be valid
102  }
103  // Read size from header
104  status = ring.peek(size, sizeof(FpFrameHeader::TokenType));
105  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
106  const U32 maxU32 = std::numeric_limits<U32>::max();
107  if (size > maxU32 - (FpFrameHeader::SIZE + HASH_DIGEST_LENGTH)) {
108  // Size is too large to process: needed would overflow
110  }
111  needed = (FpFrameHeader::SIZE + size + HASH_DIGEST_LENGTH);
112  // Check frame size
113  const U32 frameSize = size + FpFrameHeader::SIZE + HASH_DIGEST_LENGTH;
114  if (frameSize > ring.get_capacity()) {
115  // Frame size is too large for ring buffer
117  }
118  // Check for enough data to deserialize everything;
119  // otherwise break and wait for more.
120  else if (ring.get_allocated_size() < needed) {
122  }
123  // Check the checksum
124  if (not this->validate(ring, needed - HASH_DIGEST_LENGTH)) {
126  }
127  Fw::Buffer buffer = m_interface->allocate(size);
128  // Some allocators may return buffers larger than requested.
129  // That causes issues in routing; adjust size.
130  FW_ASSERT(buffer.getSize() >= size);
131  buffer.setSize(size);
132  status = ring.peek(buffer.getData(), size, FpFrameHeader::SIZE);
133  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
134  m_interface->route(buffer);
136 }
137 }
#define FW_ASSERT(...)
Definition: Assert.hpp:14
PlatformIntType NATIVE_INT_TYPE
Definition: BasicTypes.h:55
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:30
#define HASH_DIGEST_LENGTH
Definition: CRC32.hpp:18
C++-compatible configuration header for fprime configuration.
U8 * getData() const
Definition: Buffer.cpp:68
U32 getSize() const
Definition: Buffer.cpp:72
void setSize(U32 size)
Definition: Buffer.cpp:87
SerializeBufferBase & getSerializeRepr()
Definition: Buffer.cpp:107
SerializeStatus serialize(U8 val)
serialize 8-bit unsigned int
Abstract base class representing a deframing protocol.
DeframingProtocolInterface * m_interface
DeframingStatus
Status of the deframing call.
virtual Fw::Buffer allocate(const U32 size)=0
called to allocate memory, typically delegating to an allocate port call
virtual void route(Fw::Buffer &data)=0
send deframed data into the system
FprimeDeframing()
Constructor.
bool validate(Types::CircularBuffer &buffer, U32 size)
DeframingStatus deframe(Types::CircularBuffer &buffer, U32 &needed) override
FprimeFraming()
Constructor.
void frame(const U8 *const data, const U32 size, Fw::ComPacket::ComPacketType packet_type) override
Implements the frame method.
abstract class representing a framing protocol
FramingProtocolInterface * m_interface
virtual void send(Fw::Buffer &outgoing)=0
send framed data out of the framer
virtual Fw::Buffer allocate(const U32 size)=0
allocation callback to allocate memory when framing
NATIVE_UINT_TYPE get_allocated_size() const
NATIVE_UINT_TYPE get_capacity() const
Fw::SerializeStatus peek(char &value, NATIVE_UINT_TYPE offset=0) const
A container class for holding a hash buffer.
Definition: HashBuffer.hpp:26
A generic interface for creating and comparing hash values.
Definition: Hash.hpp:24
static void hash(const void *data, const NATIVE_INT_TYPE len, HashBuffer &buffer)
Definition: CRC32.cpp:29
void init()
Definition: CRC32.cpp:47
void update(const void *const data, const NATIVE_INT_TYPE len)
Definition: CRC32.cpp:53
void final(HashBuffer &buffer)
Definition: CRC32.cpp:64
SerializeStatus
forward declaration for string
@ FW_SERIALIZE_OK
Serialization/Deserialization operation was successful.
U32 TokenType
Token type for F Prime frame header.
const TokenType START_WORD
The start word for F Prime framing.
@ SIZE
Header size for F Prime frame header.