commonlib
packet_filter.h
Go to the documentation of this file.
1 
11 #pragma once
12 
13 #include <array>
14 #include <vector>
15 #include <cstdint>
16 #include <cstring>
17 
18 #include "memory.h"
19 
20 BEGIN_NAMESPACE_MEMORY
21 
22 template <typename T, std::size_t BufferSize, std::size_t HeaderLength>
24 {
25 public:
26  PacketFilter();
27 
31  virtual void clear();
32 
37  const std::vector<T>& filter(const uint8_t* data, std::size_t size);
38 
39 protected:
44  virtual bool isHeader(const uint8_t* data, std::size_t size) = 0;
45 
50  virtual std::size_t findEnd(const uint8_t* start, std::size_t size) = 0;
51 
56  virtual T convertToPacket(const uint8_t* start, std::size_t size) = 0;
57 
58 
59 private:
60  std::array<uint8_t, BufferSize> buffer;
61  std::size_t fillSize;
62  std::vector<T> packets;
63 
64 
65  std::pair<std::size_t, std::size_t> findPacket(const uint8_t* data, std::size_t size);
66  void removeFromBeginning(std::size_t size);
67  void findPackets();
68 
69 };
70 
71 template <typename T, std::size_t BufferSize, std::size_t HeaderLength>
73  : fillSize(0)
74 {
75  static_assert(BufferSize > HeaderLength, "BufferSize must be greater than HeaderLength");
76 }
77 
78 template <typename T, std::size_t BufferSize, std::size_t HeaderLength>
80 {
81  fillSize = 0;
82 }
83 
84 template <typename T, std::size_t BufferSize, std::size_t HeaderLength>
85 const std::vector<T>& PacketFilter<T, BufferSize, HeaderLength>::filter(const uint8_t* data, std::size_t size)
86 {
87  packets.clear();
88 
89  std::size_t copySize = 0;
90  while (copySize != size)
91  {
92  std::size_t remaining = BufferSize - fillSize;
93  if (size - copySize <= remaining)
94  {
95  std::memcpy(buffer.data() + fillSize, data + copySize, size - copySize);
96  fillSize += size - copySize;
97  copySize = size;
98  }
99  else
100  {
101  std::memcpy(buffer.data() + fillSize, data + copySize, remaining);
102  fillSize = BufferSize;
103  copySize += remaining;
104  }
105 
106  findPackets();
107 
108  // With full buffer header is found but no complete packet
109  if (fillSize == BufferSize)
110  removeFromBeginning(HeaderLength);
111  }
112  return packets;
113 }
114 
115 template <typename T, std::size_t BufferSize, std::size_t HeaderLength>
116 inline std::pair<std::size_t, std::size_t> PacketFilter<T, BufferSize, HeaderLength>::findPacket(const uint8_t* data, std::size_t size)
117 {
118  std::pair<std::size_t, std::size_t> result(std::string::npos, std::string::npos);
119 
120  if (size < HeaderLength)
121  return result;
122 
123  for (std::size_t i = 0; i < size - HeaderLength; i++)
124  {
125  if (isHeader(data + i, size - i))
126  {
127  result.first = i;
128  break;
129  }
130  }
131 
132  if (result.first != std::string::npos)
133  {
134  std::size_t end = findEnd(data + result.first, size - result.first);
135  if (end != std::string::npos)
136  result.second = result.first + end;
137  }
138  return result;
139 }
140 
141 template <typename T, std::size_t BufferSize, std::size_t HeaderLength>
143 {
144  if (size >= fillSize)
145  {
146  fillSize = 0;
147  }
148  else
149  {
150  std::memmove(buffer.data(), buffer.data() + size, fillSize - size);
151  fillSize -= size;
152  }
153 }
154 
155 template <typename T, std::size_t BufferSize, std::size_t HeaderLength>
157 {
158  std::pair<std::size_t, std::size_t> packetInds = findPacket(buffer.data(), fillSize);
159  if (packetInds.first != std::string::npos && packetInds.second != std::string::npos)
160  {
161  packets.emplace_back(convertToPacket(buffer.data() + packetInds.first, packetInds.second - packetInds.first + 1));
162  removeFromBeginning(packetInds.second + 1);
163  findPackets();
164  }
165  else if (packetInds.first != std::string::npos)
166  {
167  removeFromBeginning(packetInds.first);
168  }
169  else
170  {
171  removeFromBeginning(fillSize - HeaderLength);
172  }
173 }
174 
175 END_NAMESPACE_MEMORY
Definition: packet_filter.h:23
const std::vector< T > & filter(const uint8_t *data, std::size_t size)
Adds data to the internal buffer and filters out packets.
Definition: packet_filter.h:85
virtual T convertToPacket(const uint8_t *start, std::size_t size)=0
Function that converts complete packet bytes to a packet.
virtual void clear()
Clears the internal buffer.
Definition: packet_filter.h:79
virtual bool isHeader(const uint8_t *data, std::size_t size)=0
Pure virtual function that checks if the data is a header.
virtual std::size_t findEnd(const uint8_t *start, std::size_t size)=0
Function that checks if the packet is complete from the start of the header to the end of available d...