PROFINET IO Controller Stack 1.0.0
Modern C++ implementation of a PROFINET IO Controller stack
Loading...
Searching...
No Matches
util.h
Go to the documentation of this file.
1
7
8#pragma once
9
10#include <array>
11#include <chrono>
12#include <cstddef>
13#include <cstdint>
14#include <filesystem>
15#include <span>
16#include <string>
17#include <vector>
18
20
21namespace profinet
22{
23
24// =============================================================================
25// Constants
26// =============================================================================
27
28// NOLINTBEGIN(readability-identifier-naming)
30inline constexpr std::size_t MAX_ETHERNET_FRAME = 1522;
32inline constexpr std::uint16_t PROFINET_ETHERTYPE = 0x8892;
34inline constexpr std::uint16_t IP_ETHERTYPE = 0x8000;
36inline constexpr std::uint16_t VLAN_ETHERTYPE = 0x8100;
38inline constexpr int ETH_P_ALL = 0x0003;
39
41inline constexpr int macAddressLength = 6;
42
44inline constexpr int uuidLenght = 16;
45
46// @brief The number of bits in a single octet (byte), used as the base for network byte order shifts.
47static constexpr int BitsPerOctet = 8;
48
50static constexpr int OneOctetShift = BitsPerOctet; // Automatically 8
51
53static constexpr int TwoOctetsShift = BitsPerOctet * 2; // Automatically 16
54
56static constexpr int ThreeOctetsShift = BitsPerOctet * 3; // Automatically 24
57
59static constexpr std::uint8_t LowByteMask = 0xFF;
60
62inline constexpr std::size_t RECEIVE_BUFFER_LENGTH = 4096;
63
64// NOLINTEND(readability-identifier-naming)
65
67using MacAddress = std::array<std::uint8_t, macAddressLength>;
68
69// =============================================================================
70// Byte Conversion Utilities
71// =============================================================================
72
76std::string Hex4(std::uint16_t value);
77
81std::string Hex2(std::uint8_t value);
82
86std::vector<std::uint8_t> ToVec(const std::string& input);
87
93std::string HexFallback(const char* widthPrefix, std::uint32_t value, int digitWidth);
94// =============================================================================
95// Address Conversion Utilities
96// =============================================================================
97
109std::size_t SkipVlanTags(std::span<const std::uint8_t> frame) noexcept;
110
115std::string ToHex(const std::uint8_t* data, std::size_t len);
116
120std::string ToHex(const std::vector<std::uint8_t>& data);
121
126MacAddress String2Mac(const std::string& macStr);
127
131std::string Mac2String(const MacAddress& mac);
132
137std::string Mac2String(const std::uint8_t* macBytes, std::size_t len);
138
143std::string String2Ip(std::span<const std::uint8_t> ipBytes);
144
150std::string String2Ip(const std::uint8_t* ipBytes, std::size_t len);
151
156std::array<std::uint8_t, 4> Ip2String(const std::string& ipStr);
157
162std::string DecodeBytes(const std::uint8_t* data, std::size_t len);
163
167std::string DecodeBytes(const std::vector<std::uint8_t>& data);
168
169// =============================================================================
170// Socket Utilities (Linux AF_PACKET)
171// =============================================================================
172
177MacAddress GetMac(const std::string& ifname);
178
189std::filesystem::path GetExecutableDirectory();
190
196{
197 public:
203 explicit EthernetSocket(const std::string& interface, std::uint16_t ethertype = 0);
204
207
210
213
216 EthernetSocket(EthernetSocket&& other) noexcept;
217
221 EthernetSocket& operator=(EthernetSocket&& other) noexcept;
222
225 void Send(const std::vector<std::uint8_t>& frame) const override;
226
232 void SetTimeout(std::chrono::milliseconds timeout) const override;
233
237 [[nodiscard]] std::vector<std::uint8_t> Recv() const override;
238
241 [[nodiscard]] int Fd() const
242 {
243 return fd;
244 }
245
246 private:
248 int fd = -1;
249};
250
254{
255 public:
257 static constexpr double defaultTimeout = 5.0;
258
260 static constexpr int defaultReceiveBufferSize = 65536;
261
266 UdpSocket(const std::string& host, std::uint16_t port,
267 std::chrono::duration<double> timeout = std::chrono::duration<double>(defaultTimeout));
268
270 ~UdpSocket();
271
273 UdpSocket(const UdpSocket&) = delete;
274
276 UdpSocket& operator=(const UdpSocket&) = delete;
277
280 UdpSocket(UdpSocket&& other) noexcept;
281
285 UdpSocket& operator=(UdpSocket&& other) noexcept;
286
289 void Send(const std::vector<std::uint8_t>& data) const;
290
294 [[nodiscard]] std::vector<std::uint8_t> Recv(std::size_t maxLen = defaultReceiveBufferSize) const;
295
298 [[nodiscard]] int Fd() const
299 {
300 return fd;
301 }
302
303 private:
305 int fd = -1;
306};
307
308// =============================================================================
309// Timeout helper
310// =============================================================================
311
319{
320 public:
323 explicit MaxTimeout(std::chrono::duration<double> seconds)
324 : dieAfter(std::chrono::steady_clock::now() +
325 std::chrono::duration_cast<std::chrono::steady_clock::duration>(seconds))
326 {
327 }
328
331 [[nodiscard]] bool TimedOut() const
332 {
333 return std::chrono::steady_clock::now() > dieAfter;
334 }
335
338 [[nodiscard]] std::chrono::duration<double> Remaining() const
339 {
340 auto rem = dieAfter - std::chrono::steady_clock::now();
341 auto secs = std::chrono::duration<double>(rem);
342 return secs.count() > 0 ? secs : std::chrono::duration<double>(0);
343 }
344
345 private:
347 std::chrono::steady_clock::time_point dieAfter;
348};
349
350} // namespace profinet
Abstraction for sending and receiving raw Ethernet frames.
A minimal RAII wrapper around a Linux AF_PACKET raw socket bound to an interface.
Definition util.h:196
int fd
Underlying socket file descriptor, or -1 if closed/moved-from.
Definition util.h:248
EthernetSocket & operator=(const EthernetSocket &)=delete
Not copyable (owns a raw socket file descriptor).
void SetTimeout(std::chrono::milliseconds timeout) const override
Set the receive timeout.
Definition util.cpp:375
int Fd() const
The underlying file descriptor.
Definition util.h:241
void Send(const std::vector< std::uint8_t > &frame) const override
Send a raw Ethernet frame.
Definition util.cpp:366
std::vector< std::uint8_t > Recv() const override
Receive up to MAX_ETHERNET_FRAME bytes.
Definition util.cpp:386
~EthernetSocket()
Close the underlying socket.
Definition util.cpp:338
EthernetSocket(const EthernetSocket &)=delete
Not copyable (owns a raw socket file descriptor).
Abstract interface for raw Ethernet frame transport.
Time-limited-operation helper, mirroring util.py's MaxTimeout context manager.
Definition util.h:319
MaxTimeout(std::chrono::duration< double > seconds)
Start a countdown of the given duration.
Definition util.h:323
std::chrono::steady_clock::time_point dieAfter
Time point at which TimedOut() will start returning true.
Definition util.h:347
bool TimedOut() const
Whether the countdown has elapsed.
Definition util.h:331
std::chrono::duration< double > Remaining() const
Time left before the countdown elapses.
Definition util.h:338
A connected UDP socket with a timeout.
Definition util.h:254
~UdpSocket()
Close the underlying socket.
Definition util.cpp:442
std::vector< std::uint8_t > Recv(std::size_t maxLen=defaultReceiveBufferSize) const
Receive a UDP datagram from the connected peer.
Definition util.cpp:479
void Send(const std::vector< std::uint8_t > &data) const
Send a UDP datagram to the connected peer.
Definition util.cpp:470
int fd
Underlying socket file descriptor, or -1 if closed/moved-from.
Definition util.h:305
static constexpr int defaultReceiveBufferSize
Default receive buffer size.
Definition util.h:260
static constexpr double defaultTimeout
Default Timeout.
Definition util.h:257
UdpSocket & operator=(const UdpSocket &)=delete
Not copyable (owns a socket file descriptor).
UdpSocket(const UdpSocket &)=delete
Not copyable (owns a socket file descriptor).
int Fd() const
The underlying file descriptor.
Definition util.h:298
std::string Hex2(std::uint8_t value)
Format an 8-bit unsigned integer as a 2-digit hexadecimal string.
Definition util.cpp:68
constexpr std::uint16_t VLAN_ETHERTYPE
EtherType value identifying an 802.1Q VLAN tag (0x8100).
Definition util.h:36
constexpr int uuidLenght
Constant lenght of a UUID.
Definition util.h:44
std::vector< std::uint8_t > ToVec(const std::string &input)
Convert a string into a vector of raw bytes.
Definition util.cpp:73
std::string String2Ip(std::span< const std::uint8_t > ipBytes)
Format raw IPv4 address bytes as a dotted string.
Definition util.cpp:214
std::array< std::uint8_t, macAddressLength > MacAddress
A 6-byte Ethernet MAC address.
Definition util.h:67
std::array< std::uint8_t, 4 > Ip2String(const std::string &ipStr)
Parse a dotted-decimal IPv4 address string.
Definition util.cpp:230
std::filesystem::path GetExecutableDirectory()
Retrieves the absolute directory path of the currently running executable.
Definition util.cpp:494
constexpr std::uint16_t IP_ETHERTYPE
EtherType value identifying IP frames (0x8000).
Definition util.h:34
MacAddress String2Mac(const std::string &macStr)
Parse a colon-separated MAC address string.
Definition util.cpp:130
constexpr std::size_t MAX_ETHERNET_FRAME
Maximum PROFINET Ethernet frame size in bytes (including VLAN tag headroom).
Definition util.h:30
std::size_t SkipVlanTags(std::span< const std::uint8_t > frame) noexcept
Return the byte offset of the real EtherType in a raw Ethernet frame.
Definition util.cpp:89
MacAddress GetMac(const std::string &ifname)
Get the MAC address of a network interface.
Definition util.cpp:267
static constexpr int OneOctetShift
The bit-shift distance required to move data across a single octet.
Definition util.h:50
static constexpr int ThreeOctetsShift
The bit-shift distance required to move data across three octets.
Definition util.h:56
constexpr int macAddressLength
Constant lenght of a mac address.
Definition util.h:41
static constexpr int TwoOctetsShift
The bit-shift distance required to move data across two octets.
Definition util.h:53
std::string ToHex(const std::uint8_t *data, std::size_t len)
Hex-encode a byte buffer.
Definition util.cpp:112
constexpr std::uint16_t PROFINET_ETHERTYPE
EtherType value identifying PROFINET frames (0x8892).
Definition util.h:32
std::string Hex4(std::uint16_t value)
Format a 16-bit unsigned integer as a 4-digit hexadecimal string.
Definition util.cpp:63
static constexpr std::uint8_t LowByteMask
Bitmask used to isolate the lowest significant byte (8 bits) of a larger integer.
Definition util.h:59
std::string HexFallback(const char *widthPrefix, std::uint32_t value, int digitWidth)
Format a hexadecimal string with a custom prefix and dynamic width.
Definition util.cpp:78
constexpr std::size_t RECEIVE_BUFFER_LENGTH
Receive buffer length.
Definition util.h:62
constexpr int ETH_P_ALL
Linux AF_PACKET protocol value matching every EtherType.
Definition util.h:38
std::string Mac2String(const MacAddress &mac)
Format a MAC address as a colon-separated string.
Definition util.cpp:196
std::string DecodeBytes(const std::uint8_t *data, std::size_t len)
Decode bytes to a UTF-8 string, stripping trailing NUL bytes.
Definition util.cpp:247
static constexpr int BitsPerOctet
Definition util.h:47