pcap_reader.cpp
Go to the documentation of this file.
1 // *****************************************************************************
2 //
3 // © Copyright 2020, Septentrio NV/SA.
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
8 // 1. Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // 2. Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // 3. Neither the name of the copyright holder nor the names of its
14 // contributors may be used to endorse or promote products derived
15 // from this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 // POSSIBILITY OF SUCH DAMAGE.
28 //
29 // *****************************************************************************
30 
32 
33 #include <chrono>
34 #include <net/ethernet.h>
35 #include <netinet/ip.h>
36 #include <netinet/tcp.h>
38 #include <thread>
39 
51 namespace pcapReader {
52 
54  node_(node), m_dataBuff{buffer}
55  {
56  }
57 
59 
60  bool PcapDevice::connect(const char* device)
61  {
62  if (isConnected())
63  return true;
64  // Try to open pcap file
65  if ((m_device = pcap_open_offline(device, m_errBuff)) == nullptr)
66  return false;
67 
68  m_deviceName = (char*)device;
69  // Try to compile filter program
70  if (pcap_compile(m_device, &m_pktFilter, "tcp dst port 3001", 1,
71  PCAP_NETMASK_UNKNOWN) != 0)
72  return false;
73 
74  node_->log(LogLevel::INFO, "Connected to" + std::string(m_deviceName));
75  return true;
76  }
77 
79  {
80  if (!isConnected())
81  return;
82 
83  pcap_close(m_device);
84  m_device = nullptr;
85  node_->log(LogLevel::INFO, "Disconnected from " + std::string(m_deviceName));
86  }
87 
88  bool PcapDevice::isConnected() const { return m_device; }
89 
91  {
92  if (!isConnected())
93  return READ_ERROR;
94 
95  struct pcap_pkthdr* header;
96  const u_char* pktData;
97  int result;
98 
99  result = pcap_next_ex(m_device, &header, &pktData);
100 
101  if (result >= 0)
102  {
103  auto ipHdr =
104  reinterpret_cast<const iphdr*>(pktData + sizeof(struct ethhdr));
105  uint32_t ipHdrLen = ipHdr->ihl * 4u;
106 
107  switch (ipHdr->protocol)
108  {
109  case 6:
110  {
111  if (header->len == 54)
112  {
113  return READ_SUCCESS;
114  }
115  bool storePkt = true;
116 
117  if (!m_lastPkt.empty())
118  {
119  auto tcpHdr = reinterpret_cast<const tcphdr*>(
120  pktData + ipHdrLen + sizeof(struct ethhdr));
121 
122  auto lastIpHdr = reinterpret_cast<const iphdr*>(&(m_lastPkt[0]));
123  uint32_t lastIpHdrLen = lastIpHdr->ihl * 4u;
124  auto lastTcpHdr = reinterpret_cast<const tcphdr*>(
125  &(m_lastPkt[0]) + lastIpHdrLen);
126  uint16_t lastLen =
127  ntohs(static_cast<uint16_t>(lastIpHdr->tot_len));
128  uint16_t newLen = ntohs(static_cast<uint16_t>(ipHdr->tot_len));
129  uint32_t lastSeq = ntohl(lastTcpHdr->seq);
130  uint32_t newSeq = ntohl(tcpHdr->seq);
131 
132  if (newSeq != lastSeq)
133  {
134  uint32_t dataOffset = lastTcpHdr->doff * 4;
135  m_dataBuff.insert(m_dataBuff.end(),
136  m_lastPkt.begin() + lastIpHdrLen +
137  dataOffset,
138  m_lastPkt.end());
139  } else if (newLen <= lastLen)
140  {
141  storePkt = false;
142  }
143  }
144 
145  if (storePkt)
146  {
147  m_lastPkt.clear();
148  m_lastPkt.insert(m_lastPkt.end(),
149  pktData + sizeof(struct ethhdr),
150  pktData + header->len);
151  }
152  break;
153  }
154 
155  default:
156  {
158  "Skipping protocol: " + std::to_string(result));
159  return READ_ERROR;
160  }
161  }
162  std::this_thread::sleep_for(std::chrono::milliseconds(1));
163 
164  return READ_SUCCESS;
165  } else if (result == -2)
166  {
168  "Done reading from " + std::string(m_deviceName));
169  if (!m_lastPkt.empty())
170  {
171  auto lastIpHdr = reinterpret_cast<const iphdr*>(&(m_lastPkt[0]));
172  uint32_t ipHdrLength = lastIpHdr->ihl * 4u;
173 
174  auto lastTcpHdr =
175  reinterpret_cast<const tcphdr*>(&(m_lastPkt[0]) + ipHdrLength);
176  uint32_t dataOffset = lastTcpHdr->doff * 4u;
177 
178  m_dataBuff.insert(m_dataBuff.end(),
179  m_lastPkt.begin() + ipHdrLength + dataOffset,
180  m_lastPkt.end());
181 
182  m_lastPkt.clear();
183  }
184  disconnect();
185  return READ_SUCCESS;
186  } else
187  {
188  node_->log(LogLevel::ERROR, "Error reading data");
189  return READ_ERROR;
190  }
191  }
192 } // namespace pcapReader
ReadResult read()
Attempt to read a packet and store data to buffer.
Definition: pcap_reader.cpp:90
std::vector< uint8_t > buffer_t
Definition: pcap_reader.hpp:49
~PcapDevice()
Destructor for PcapDevice.
Definition: pcap_reader.cpp:58
void disconnect()
Close connected file.
Definition: pcap_reader.cpp:78
bool isConnected() const
Check if file is open and healthy.
Definition: pcap_reader.cpp:88
void log(LogLevel logLevel, const std::string &s)
Log function to provide abstraction of ROS loggers.
Definition: typedefs.hpp:231
bool connect(const char *device)
Try to open a pcap file.
Definition: pcap_reader.cpp:60
Data read successfully.
Definition: pcap_reader.hpp:55
char m_errBuff[BUFFSIZE]
ROSaicNodeBase * node_
Pointer to the node.
Declares a class for handling pcap files.
ReadResult
Read operation status.
Definition: pcap_reader.hpp:52
buffer_t & m_dataBuff
Reference to raw data buffer to write to.
This class is the base class for abstraction.
Definition: typedefs.hpp:174
const std::string header
PcapDevice(ROSaicNodeBase *node, buffer_t &buffer)
Constructor for PcapDevice.
Definition: pcap_reader.cpp:53
pcap_t * m_device
File handle to pcap file.


septentrio_gnss_driver
Author(s): Tibor Dome
autogenerated on Sat Mar 11 2023 03:12:55