.. _program_listing_file_pcap_packet.hh: Program Listing for File packet.hh ================================== |exhale_lsh| :ref:`Return to documentation for file ` (``pcap/packet.hh``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp // SPDX-License-Identifier: LGPL-3.0-or-later /* pcap/packet.hh - libnokogiri pcap packets */ #if !defined(LIBNOKOGIRI_PCAP_PACKET_HH) #define LIBNOKOGIRI_PCAP_PACKET_HH #include #include #include #include #include #include #include #include #include namespace libnokogiri::pcap { using libnokogiri::internal::enum_pair_t; enum struct packet_type_t : uint8_t { Standard = 0x00, Modified = 0x01, }; const std::array, 2> packet_type_s{{ { packet_type_t::Standard, "Standard"sv }, { packet_type_t::Modified, "Modified"sv } }}; struct packet_header_t final { private: std::uint32_t _timestamp; std::uint32_t _usecs; std::uint32_t _have; std::uint32_t _was; public: constexpr packet_header_t() noexcept : _timestamp{0U}, _usecs{0U}, _have{0U}, _was{0U} { /* NOP */ } constexpr packet_header_t(std::uint32_t timestamp, std::uint32_t useconds, std::uint32_t pkt_len_have, std::uint32_t pkt_len_actual) noexcept : _timestamp{timestamp}, _usecs{useconds}, _have{pkt_len_have}, _was{pkt_len_actual} { /* NOP */ } packet_header_t(const packet_header_t&) = delete; packet_header_t& operator=(const packet_header_t&) = delete; packet_header_t(packet_header_t&&) = default; packet_header_t& operator=(packet_header_t&&) = default; [[nodiscard]] std::uint32_t timestamp() const noexcept { return _timestamp; } void timestamp(const std::uint32_t timestamp) noexcept { _timestamp = timestamp; } [[nodiscard]] std::uint32_t useconds() const noexcept { return _usecs; } void useconds(const std::uint32_t useconds) noexcept { _usecs = useconds; } [[nodiscard]] std::uint32_t captured_len() const noexcept { return _have; } void captured_len(const std::uint32_t captured_len) noexcept { _have = captured_len; } [[nodiscard]] std::uint32_t actual_len() const noexcept { return _was; } void actual_len(const std::uint32_t actual_len) noexcept { _was = actual_len; } [[nodiscard]] bool full_packet() const noexcept { return _was == _have; } }; struct packet_header_modified_t final { private: packet_header_t _base_header; std::uint32_t _if_index; std::uint16_t _proto; std::uint8_t _type; std::uint8_t _padding; public: constexpr packet_header_modified_t() noexcept : _base_header{}, _if_index{0U}, _proto{0U}, _type{0U}, _padding{0U} { /* NOP */ } constexpr packet_header_modified_t(packet_header_t&& base_header, std::uint32_t if_index, std::uint16_t protocol, std::uint8_t type) noexcept : _base_header{std::move(base_header)}, _if_index{if_index}, _proto{protocol}, _type{type}, _padding{0U} { /* NOP */ } packet_header_modified_t(std::nullptr_t) noexcept { /* NOP */ } packet_header_modified_t(const packet_header_modified_t&) = delete; packet_header_modified_t& operator=(const packet_header_modified_t&) = delete; packet_header_modified_t(packet_header_modified_t&&) = default; packet_header_modified_t& operator=(packet_header_modified_t&&) = default; [[nodiscard]] const packet_header_t& base_header() const noexcept { return _base_header; } void base_header(packet_header_t&& base_header) noexcept { _base_header = std::move(base_header); } [[nodiscard]] std::uint32_t interface_index() const noexcept { return _if_index; } void interface_index(std::uint32_t interface_index) noexcept { _if_index = interface_index; } [[nodiscard]] std::uint16_t protocol() const noexcept { return _proto; } void protocol(std::uint16_t protocol) noexcept { _proto = protocol; } [[nodiscard]] std::uint8_t type() const noexcept { return _type; } void type(std::uint8_t type) noexcept { _type = type; } }; // /*! \struct libnokogiri::pcap::packet_t // \brief pcap packet template // This template provides the framework for reading and writing packets. // They can have custom headers, but the two standardized packets are already // specified as libnokogiri::pcap::generic_packet_t and libnokogiri::pcap::modified_packet_t . // All this template does is change out the packet header type, the rest of the logic is identical. // */ // template // struct packet_t final { // public: // using data_t = std::optional>; // private: // T _packet_header; // std::uintptr_t _offset; // data_t _data; // public: // constexpr packet_t() noexcept : // _packet_header{}, _offset{0U}, _data{std::nullopt} // { /* NOP */ } // constexpr packet_t(T header, std::uintptr_t offset, data_t data) noexcept : // _packet_header{header}, _offset{offset}, _data{data} // { /* NOP */ } // /*! Retrieve the packet header */ // [[nodiscard]] // T header() const noexcept { return _packet_header; } // /*! Set the packet header */ // void header(T header) noexcept { _packet_header = header; } // /*! Retrieve the offset in the file the packet is located at */ // [[nodiscard]] // std::uintptr_t packet_offset() const noexcept { return _offset; } // /*! Set the offset in the file the packet is located at */ // void packet_offset(std::uintptr_t packet_offset) noexcept { _offset = packet_offset; } // /*! Retrieve the packet data */ // [[nodiscard]] // data_t packet_data() const noexcept { return _data; } // /*! Set the packet data */ // void packet_data(data_t packet_data) noexcept { _data = packet_data; } // }; // /*! Type alias for generic conforming pcap packets with the standard header */ // template // using generic_packet_t = packet_t; // /*! Type alias for packets from the modified pcap files */ // template // using modified_packet_t = packet_t; struct packet_t { public: using pkt_header_t = std::variant< std::monostate, packet_header_t, packet_header_modified_t >; private: std::vector _raw_data; pkt_header_t _packet_header; template [[nodiscard]] std::enable_if_t< std::is_pod_v && !libnokogiri::internal::has_nullable_ctor_v && !std::is_same_v, T*> index(const std::size_t offset) { if (offset < _raw_data.size()) { return new (reinterpret_cast(_raw_data.data()) + (offset * sizeof(T))) T{}; } return nullptr; } template [[nodiscard]] std::enable_if_t< libnokogiri::internal::has_nullable_ctor_v && !std::is_same_v, T*> index(const std::size_t offset) { if (offset < _raw_data.size()) { return new (reinterpret_cast(_raw_data.data()) + (offset * sizeof(T))) T{nullptr}; } return nullptr; } template [[nodiscard]] std::enable_if_t, void*> index(const std::size_t offset) { if (offset < _raw_data.size()) { return reinterpret_cast(_raw_data.data()) + offset; } return nullptr; } public: packet_t(std::size_t length, pkt_header_t header = {}) noexcept : _raw_data{std::vector(length)}, _packet_header{std::move(header)} { /* NOP */ } packet_t(const packet_t&) = delete; packet_t& operator=(const packet_t&) = delete; packet_t(packet_t&&) = default; packet_t& operator=(packet_t&&) = default; [[nodiscard]] std::size_t length() const noexcept { return _raw_data.size(); } [[nodiscard]] pkt_header_t& header() noexcept { return _packet_header; } [[nodiscard]] bool is_complete() const noexcept { return std::visit([](auto& header) -> bool { using T = std::decay_t; if constexpr (std::is_same_v) { return header.base_header().full_packet(); } else if constexpr (std::is_same_v) { return header.full_packet(); } else { return false; } }, _packet_header); } template [[nodiscard]] T& as() { *index(); } template [[nodiscard]] T *operator [](const off_t idx) { return index(idx); } [[nodiscard]] auto begin() noexcept { return _raw_data.begin(); } [[nodiscard]] auto end() noexcept { return _raw_data.end(); } template [[nodiscard]] const T *operator [](const off_t idx) const { return index(idx); } template [[nodiscard]] T *at(const off_t idx) { return index(idx); } template [[nodiscard]] const T *at(const off_t idx) const { return index(idx); } void *address(const off_t offset) noexcept { return index(offset); } }; struct packet_storage_t final { private: std::uint32_t _len; std::uintptr_t _offset; packet_t _packet_cache; public: packet_storage_t() noexcept : _len{0U}, _offset{0U}, _packet_cache{0} { /* NOP */ } packet_storage_t(std::uint32_t len, std::uintptr_t offset) noexcept : _len{len}, _offset{offset}, _packet_cache{0} { /* NOP */ } packet_storage_t(std::uint32_t len, std::uintptr_t offset, packet_t&& packet) noexcept : _len{len}, _offset{offset}, _packet_cache{std::move(packet)} { /* NOP */ } packet_storage_t(const packet_storage_t&) = delete; packet_storage_t& operator=(const packet_storage_t&) = delete; packet_storage_t(packet_storage_t&&) = default; packet_storage_t& operator=(packet_storage_t&&) = default; [[nodiscard]] std::uint32_t length() const noexcept { return _len; } [[nodiscard]] std::uintptr_t offset() const noexcept { return _offset; } [[nodiscard]] packet_t& get_packet() noexcept { return _packet_cache; } void set_packet(packet_t&& pkt) noexcept { _packet_cache = std::move(pkt); } }; } #endif /* LIBNOKOGIRI_PCAP_PACKET_HH */