30#include <asio/ip/address_v4.hpp>
44std::string
Hex4(std::uint16_t value)
46 return std::format(
"0x{:04X}", value);
49std::string
Hex2(std::uint8_t value)
51 return std::format(
"0x{:02X}", value);
54std::vector<std::uint8_t>
ToVec(
const std::string& input)
56 return {input.begin(), input.end()};
59std::string
HexFallback(
const char* widthPrefix, std::uint32_t value,
int digitWidth)
63 return std::format(
"{}(0x{:0{}X})", widthPrefix, value, digitWidth);
74 if (
frame.size() < ethernetHeaderSize)
76 return ethernetHeaderSize;
80 r.
SkipTo(ethernetHeaderSize);
82 while (r.
Remaining() >= 2U *
sizeof(std::uint16_t))
84 const std::size_t tpidOffset = r.
Position();
87 const std::uint16_t tpid = r.
U16();
93 r.
Skip(
sizeof(std::uint16_t));
104std::string
ToHex(
const std::uint8_t* data, std::size_t len)
107 out.reserve(len * 2);
108 static const char* digits =
"0123456789abcdef";
109 for (std::size_t i = 0; i < len; ++i)
111 out.push_back(digits[data[i] >> 4]);
112 out.push_back(digits[data[i] & 0x0F]);
117std::string
ToHex(
const std::vector<std::uint8_t>& data)
119 return ToHex(data.data(), data.size());
125 static constexpr std::size_t expectedStringLength = 17;
126 static constexpr std::size_t singleByteHexLength = 2;
127 static constexpr int hexBase = 16;
130 static constexpr std::array<std::size_t, 5> delimiterIndices = {2, 5, 8, 11, 14};
133 if (macStr.size() != expectedStringLength)
135 throw InvalidMACError(std::format(
"Invalid MAC address length: '{}'", macStr));
140 bool isValidStructure =
true;
141 for (std::size_t i = 0; i < expectedStringLength; ++i)
144 const bool isDelimiterIdx = std::ranges::any_of(delimiterIndices,
150 if (macStr[i] !=
':')
152 isValidStructure =
false;
158 if (std::isxdigit(
static_cast<unsigned char>(macStr[i])) == 0)
160 isValidStructure =
false;
166 if (!isValidStructure)
168 throw InvalidMACError(std::format(
"Invalid MAC address characters or format: '{}'", macStr));
172 std::string_view macView{macStr};
175 static constexpr std::size_t hexPairStride = 3;
178 const std::size_t offset = i * hexPairStride;
179 const std::string_view hexPair = macView.substr(offset, singleByteHexLength);
182 mac.at(i) =
static_cast<std::uint8_t
>(std::stoul(std::string(hexPair),
nullptr, hexBase));
193std::string
Mac2String(
const std::uint8_t* macBytes, std::size_t len)
197 throw InvalidMACError(
"MAC address must be 6 bytes, got " + std::to_string(len));
200 const std::string macStr = std::format(
"{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
201 macBytes[0], macBytes[1], macBytes[2],
202 macBytes[3], macBytes[4], macBytes[5]);
206std::string
String2Ip(std::span<const std::uint8_t> ipBytes)
208 if (ipBytes.size() < 4)
210 throw InvalidIPError(
"IP address must be at least 4 bytes, got " + std::to_string(ipBytes.size()));
213 return std::to_string(ipBytes[0]) +
"." + std::to_string(ipBytes[1]) +
"." +
214 std::to_string(ipBytes[2]) +
"." + std::to_string(ipBytes[3]);
217std::string
String2Ip(
const std::uint8_t* ipBytes, std::size_t len)
219 return String2Ip(std::span<const std::uint8_t>(ipBytes, len));
222std::array<std::uint8_t, 4>
Ip2String(
const std::string& ipStr)
230 const auto address = asio::ip::make_address_v4(ipStr, ec);
237 const auto bytes = address.to_bytes();
248 std::size_t end = len;
249 while (end > 0 && data[end - 1] == 0)
254 return std::string(
reinterpret_cast<const char*
>(data), end);
Invalid IP address format.
Invalid MAC address format.
MacAddress GetMac(const std::string &interface) override
Get the MAC address of a network interface.
Lightweight cursor for parsing a big-endian byte buffer without copies.
std::size_t Position() const
Current read offset from the start of the buffer.
std::size_t Remaining() const
Number of bytes not yet consumed.
void SkipTo(std::size_t offset)
Move the read position to an absolute byte offset.
void Skip(std::size_t n)
Advance the read position without returning the skipped bytes.
std::uint16_t U16()
Read and consume a big-endian 16-bit value.
Declares exceptions and error types used by the PROFINET IO controller stack.
constexpr std::uint16_t ETHERTYPE_VLAN_AD
EtherType used by VLAN frames, 802.1ad VLAN TPID (0x88A8).
constexpr std::uint16_t ETHERTYPE_VLAN
EtherType used by VLAN frames, 802.1Q VLAN TPID (0x8100).
constexpr std::uint16_t ETHERTYPE_VLAN_LEGACY
EtherType used by VLAN frames, 802.1Q double-tagging legacy VLAN TPID (0x9100).
std::string Hex2(std::uint8_t value)
Format an 8-bit unsigned integer as a 2-digit hexadecimal string.
MacAddress GetInterfaceMac(const std::string &interface)
Get the MAC address assigned to a network interface.
std::vector< std::uint8_t > ToVec(const std::string &input)
Convert a string into a vector of raw bytes.
std::string String2Ip(std::span< const std::uint8_t > ipBytes)
Format raw IPv4 address bytes as a dotted string.
std::array< std::uint8_t, macAddressLength > MacAddress
A 6-byte Ethernet MAC address.
std::array< std::uint8_t, 4 > Ip2String(const std::string &ipStr)
Parse a dotted-decimal IPv4 address string.
MacAddress String2Mac(const std::string &macStr)
Parse a colon-separated MAC address string.
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.
constexpr int macAddressLength
Constant lenght of a mac address.
std::string ToHex(const std::uint8_t *data, std::size_t len)
Hex-encode a byte buffer.
std::string Hex4(std::uint16_t value)
Format a 16-bit unsigned integer as a 4-digit hexadecimal string.
std::string HexFallback(const char *widthPrefix, std::uint32_t value, int digitWidth)
Format a hexadecimal string with a custom prefix and dynamic width.
std::string Mac2String(const MacAddress &mac)
Format a MAC address as a colon-separated string.
std::string DecodeBytes(const std::uint8_t *data, std::size_t len)
Decode bytes to a UTF-8 string, stripping trailing NUL bytes.
Declares PROFINET RT_CLASS_1 cyclic frame and IOCR data structures.
Declares Linux Ethernet, addressing, timing, and utility helpers used by the PROFINET stack.
Generic helpers for reading and writing integer and byte data in big- and little-endian wire formats.