diff --git a/Packet++/header/RawPacket.h b/Packet++/header/RawPacket.h index 41cb56a2a0..51c346f2a7 100644 --- a/Packet++/header/RawPacket.h +++ b/Packet++/header/RawPacket.h @@ -251,20 +251,102 @@ namespace pcpp /// Max packet size supported #define PCPP_MAX_PACKET_SIZE 65536 + namespace internal + { + // TODO: Class is experimental and should not be used in user code yet. Eventually promote it to public API + /// @brief A base class for raw packet classes, containing common attributes and methods. + class RawPacketBase + { + protected: + /// @brief A default constructor that zero initializes the timestamp and sets the link layer type to + /// Ethernet. + RawPacketBase() = default; + /// @brief A constructor that initializes the timestamp and link layer type. + /// @param[in] timestamp The timestamp packet was received by the NIC (in nsec precision) + /// @param[in] linkLayerType The link layer type of the packet, defaulting to Ethernet. + explicit RawPacketBase(timespec timestamp, LinkLayerType linkLayerType = LinkLayerType::LINKTYPE_ETHERNET); + /// @brief A constructor that initializes the timestamp and link layer type. + /// @param[in] timestamp The timestamp packet was received by the NIC (in usec precision) + /// @param[in] linkLayerType The link layer type of the packet, defaulting to Ethernet. + explicit RawPacketBase(timeval timestamp, LinkLayerType linkLayerType = LinkLayerType::LINKTYPE_ETHERNET); + + // Copy and move constructors and assignment operators are protected to prevent slicing + RawPacketBase(const RawPacketBase&) = default; + RawPacketBase(RawPacketBase&&) = default; + RawPacketBase& operator=(const RawPacketBase&) = default; + RawPacketBase& operator=(RawPacketBase&&) = default; + + public: + virtual ~RawPacketBase() = default; + + /// @brief Get the link layer type of the packet. + /// @return A LinkLayerType enum value representing the link layer type of the packet. + LinkLayerType getLinkLayerType() const + { + return m_LinkLayerType; + } + + /// @brief Return the timestamp of the packet. + /// @return The timestamp of the packet with nanosecond precision. + timespec getPacketTimeStamp() const + { + return m_TimeStamp; + } + + /// Set raw packet timestamp with usec precision + /// @param[in] timestamp The timestamp to set (with usec precision) + /// @return True if timestamp was set successfully, false otherwise + bool setPacketTimeStamp(timeval timestamp); + + /// Set raw packet timestamp with nsec precision + /// @param[in] timestamp The timestamp to set (with nsec precision) + /// @return True if timestamp was set successfully, false otherwise + bool setPacketTimeStamp(timespec timestamp); + + // To be implemented in derived classes: + + // bool isContiguous() const = 0; <- eventually needed for MBufRawPacket to indicate if the mbuf is a single + // segment or not. + + // uint8_t* getRawData() = 0; <- maybe protected, so direct modification is not allowed? Expose maybe a span + // proxy instead for public? + + // uint8_t const* getRawData() const = 0; + + // int getRawDataLen() const = 0; <- should probably return size_t for consistency with modern C++ + // practices, but the current API uses int + + // Mutators: + // void setRawData(...) = 0; + // bool appendData(...) = 0; + // bool insertData(...) = 0; + // void removeData(...) = 0; + // void clear(...) = 0; + + protected: + void setLinkLayerType(LinkLayerType linkLayerType) + { + m_LinkLayerType = linkLayerType; + } + + private: + timespec m_TimeStamp{}; // Zero initialized + LinkLayerType m_LinkLayerType = LinkLayerType::LINKTYPE_ETHERNET; + }; + } // namespace internal + /// @class RawPacket /// This class holds the packet as raw (not parsed) data. The data is held as byte array. In addition to the data /// itself every instance also holds a timestamp representing the time the packet was received by the NIC. RawPacket /// instance isn't read only. The user can change the packet data, add or remove data, etc. - class RawPacket + class RawPacket : public internal::RawPacketBase { protected: uint8_t* m_RawData = nullptr; int m_RawDataLen = 0; int m_FrameLength = 0; - timespec m_TimeStamp{}; // Zero initialized bool m_DeleteRawDataAtDestructor = true; bool m_RawPacketSet = false; - LinkLayerType m_LinkLayerType = LinkLayerType::LINKTYPE_ETHERNET; void copyDataFrom(const RawPacket& other, bool allocateData = true); @@ -372,13 +454,6 @@ namespace pcpp return m_RawData; } - /// Get the link layer type - /// @return the type of the link layer - LinkLayerType getLinkLayerType() const - { - return m_LinkLayerType; - } - /// This static method validates whether a link type integer value is valid /// @param[in] linkTypeValue Link type integer value /// @return True if the link type value is valid and can be casted into LinkLayerType enum, false otherwise @@ -397,22 +472,6 @@ namespace pcpp { return m_FrameLength; } - /// Get raw data timestamp - /// @return Raw data timestamp - timespec getPacketTimeStamp() const - { - return m_TimeStamp; - } - - /// Set raw packet timestamp with usec precision - /// @param[in] timestamp The timestamp to set (with usec precision) - /// @return True if timestamp was set successfully, false otherwise - virtual bool setPacketTimeStamp(timeval timestamp); - - /// Set raw packet timestamp with nsec precision - /// @param[in] timestamp The timestamp to set (with nsec precision) - /// @return True if timestamp was set successfully, false otherwise - virtual bool setPacketTimeStamp(timespec timestamp); /// Get an indication whether raw data was already set for this instance. /// @return True if raw data was set for this instance. Raw data can be set using the non-default constructor, diff --git a/Packet++/src/RawPacket.cpp b/Packet++/src/RawPacket.cpp index 08022885c0..520396c4db 100644 --- a/Packet++/src/RawPacket.cpp +++ b/Packet++/src/RawPacket.cpp @@ -7,6 +7,28 @@ namespace pcpp { + namespace internal + { + RawPacketBase::RawPacketBase(timespec timestamp, LinkLayerType linkLayerType) + : m_TimeStamp(timestamp), m_LinkLayerType(linkLayerType) + {} + + RawPacketBase::RawPacketBase(timeval timestamp, LinkLayerType linkLayerType) + : m_TimeStamp(internal::toTimespec(timestamp)), m_LinkLayerType(linkLayerType) + {} + + bool RawPacketBase::setPacketTimeStamp(timeval timestamp) + { + return setPacketTimeStamp(internal::toTimespec(timestamp)); + } + + bool RawPacketBase::setPacketTimeStamp(timespec timestamp) + { + m_TimeStamp = timestamp; + return true; + } + } // namespace internal + RawPacket::RawPacket(const uint8_t* pRawData, int rawDataLen, timeval timestamp, bool deleteRawDataAtDestructor, LinkLayerType layerType) : RawPacket(pRawData, rawDataLen, internal::toTimespec(timestamp), deleteRawDataAtDestructor, layerType) @@ -14,9 +36,9 @@ namespace pcpp RawPacket::RawPacket(const uint8_t* pRawData, int rawDataLen, timespec timestamp, bool deleteRawDataAtDestructor, LinkLayerType layerType) - : m_RawData(const_cast(pRawData)), m_RawDataLen(rawDataLen), m_FrameLength(rawDataLen), - m_TimeStamp(timestamp), m_DeleteRawDataAtDestructor(deleteRawDataAtDestructor), m_RawPacketSet(true), - m_LinkLayerType(layerType) + : internal::RawPacketBase(timestamp, layerType), m_RawData(const_cast(pRawData)), + m_RawDataLen(rawDataLen), m_FrameLength(rawDataLen), m_DeleteRawDataAtDestructor(deleteRawDataAtDestructor), + m_RawPacketSet(true) {} RawPacket::~RawPacket() @@ -52,7 +74,8 @@ namespace pcpp if (!other.m_RawPacketSet) return; - m_TimeStamp = other.m_TimeStamp; + // Call base class copy assignment operator to copy timestamp and link layer type + RawPacketBase::operator=(other); if (allocateData) { @@ -62,7 +85,6 @@ namespace pcpp } memcpy(m_RawData, other.m_RawData, other.m_RawDataLen); - m_LinkLayerType = other.m_LinkLayerType; m_FrameLength = other.m_FrameLength; m_RawPacketSet = true; } @@ -81,9 +103,9 @@ namespace pcpp m_FrameLength = (frameLength == -1) ? rawDataLen : frameLength; m_RawData = (uint8_t*)pRawData; m_RawDataLen = rawDataLen; - m_TimeStamp = timestamp; + setPacketTimeStamp(timestamp); // Always returns true + setLinkLayerType(layerType); m_RawPacketSet = true; - m_LinkLayerType = layerType; return true; } @@ -175,17 +197,6 @@ namespace pcpp return true; } - bool RawPacket::setPacketTimeStamp(timeval timestamp) - { - return setPacketTimeStamp(internal::toTimespec(timestamp)); - } - - bool RawPacket::setPacketTimeStamp(timespec timestamp) - { - m_TimeStamp = timestamp; - return true; - } - bool RawPacket::isLinkTypeValid(int linkTypeValue) { if ((linkTypeValue < 0 || linkTypeValue > 264) && linkTypeValue != 276) diff --git a/Pcap++/src/MBufRawPacket.cpp b/Pcap++/src/MBufRawPacket.cpp index 9922205785..a6469f16f3 100644 --- a/Pcap++/src/MBufRawPacket.cpp +++ b/Pcap++/src/MBufRawPacket.cpp @@ -131,7 +131,7 @@ namespace pcpp return; } - setMBuf(newMbuf, other.m_TimeStamp); + setMBuf(newMbuf, other.getPacketTimeStamp()); m_RawPacketSet = false; @@ -217,10 +217,10 @@ namespace pcpp m_RawDataLen = rte_pktmbuf_pkt_len(m_MBuf); memcpy(m_RawData, pRawData, m_RawDataLen); delete[] pRawData; - m_TimeStamp = timestamp; + setPacketTimeStamp(timestamp); m_RawPacketSet = true; m_FrameLength = frameLength; - m_LinkLayerType = layerType; + setLinkLayerType(layerType); return true; }