Skip to content

Commit 95ace2d

Browse files
authored
Add overloads to setRawData that take explicit ownership parameter. (#2036)
1 parent 5889e9f commit 95ace2d

6 files changed

Lines changed: 154 additions & 57 deletions

File tree

Packet++/header/RawPacket.h

Lines changed: 78 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#endif
1010
#include <stddef.h>
1111

12+
#include "DeprecationUtils.h"
13+
1214
/// @file
1315

1416
/// @namespace pcpp
@@ -262,7 +264,7 @@ namespace pcpp
262264
int m_RawDataLen = 0;
263265
int m_FrameLength = 0;
264266
timespec m_TimeStamp{}; // Zero initialized
265-
bool m_DeleteRawDataAtDestructor = true;
267+
bool m_OwnsRawData = false;
266268
bool m_RawPacketSet = false;
267269
LinkLayerType m_LinkLayerType = LinkLayerType::LINKTYPE_ETHERNET;
268270

@@ -273,7 +275,7 @@ namespace pcpp
273275
/// - data pointer is set to nullptr
274276
/// - data length is set to 0
275277
/// - frame length is set to 0
276-
/// - deleteRawDataAtDestructor is set to 'true'
278+
/// - takeOwnership is set to 'false'
277279
/// - timestamp is set to 0
278280
/// - layer type is set to Ethernet
279281
RawPacket() = default;
@@ -285,10 +287,10 @@ namespace pcpp
285287
/// @param[in] pRawData A pointer to the raw data
286288
/// @param[in] rawDataLen The raw data length in bytes
287289
/// @param[in] timestamp The timestamp packet was received by the NIC (in usec precision)
288-
/// @param[in] deleteRawDataAtDestructor An indicator whether raw data pointer should be freed when the instance
289-
/// is freed or not. If set to 'true' than pRawData will be freed when instanced is being freed
290+
/// @param[in] takeOwnership If 'true' the RawPacket will take ownership of the pRawData pointer and will
291+
/// free it when the RawPacket instance is destroyed or the buffer is replaced.
290292
/// @param[in] layerType The link layer type of this raw packet. The default is Ethernet
291-
RawPacket(const uint8_t* pRawData, int rawDataLen, timeval timestamp, bool deleteRawDataAtDestructor,
293+
RawPacket(const uint8_t* pRawData, int rawDataLen, timeval timestamp, bool takeOwnership,
292294
LinkLayerType layerType = LINKTYPE_ETHERNET);
293295

294296
/// A constructor that receives a pointer to the raw data (allocated elsewhere). This constructor is usually
@@ -298,13 +300,13 @@ namespace pcpp
298300
/// @param[in] pRawData A pointer to the raw data
299301
/// @param[in] rawDataLen The raw data length in bytes
300302
/// @param[in] timestamp The timestamp packet was received by the NIC (in nsec precision)
301-
/// @param[in] deleteRawDataAtDestructor An indicator whether raw data pointer should be freed when the instance
302-
/// is freed or not. If set to 'true' than pRawData will be freed when instanced is being freed
303+
/// @param[in] takeOwnership If 'true' the RawPacket will take ownership of the pRawData pointer and will
304+
/// free it when the RawPacket instance is destroyed or the buffer is replaced.
303305
/// @param[in] layerType The link layer type of this raw packet. The default is Ethernet
304-
RawPacket(const uint8_t* pRawData, int rawDataLen, timespec timestamp, bool deleteRawDataAtDestructor,
306+
RawPacket(const uint8_t* pRawData, int rawDataLen, timespec timestamp, bool takeOwnership,
305307
LinkLayerType layerType = LINKTYPE_ETHERNET);
306308

307-
/// A destructor for this class. Frees the raw data if deleteRawDataAtDestructor was set to 'true'
309+
/// A destructor for this class. Frees the raw data if takeOwnership was set to 'true'
308310
virtual ~RawPacket();
309311

310312
/// A copy constructor that copies all data from another instance. Notice all raw data is copied (using memcpy),
@@ -313,7 +315,7 @@ namespace pcpp
313315
RawPacket(const RawPacket& other);
314316

315317
/// Assignment operator overload for this class. When using this operator on an already initialized RawPacket
316-
/// instance, the original raw data is freed first if deleteRawDataAtDestructor was set to 'true'.
318+
/// instance, the original raw data is freed first if takeOwnership was set to 'true'.
317319
/// Then the other instance is copied to this instance, the same way the copy constructor works
318320
/// @param[in] other The instance to copy from
319321
RawPacket& operator=(const RawPacket& other);
@@ -328,7 +330,7 @@ namespace pcpp
328330
return 0;
329331
}
330332

331-
/// Set a raw data. If data was already set and deleteRawDataAtDestructor was set to 'true' the old data will be
333+
/// Set a raw data. If data was already set and takeOwnership was set to 'true' the old data will be
332334
/// freed first
333335
/// @param[in] pRawData A pointer to the new raw data
334336
/// @param[in] rawDataLen The new raw data length in bytes
@@ -338,10 +340,36 @@ namespace pcpp
338340
/// actual packet length. This parameter represents the packet length. This parameter is optional, if not set or
339341
/// set to -1 it is assumed both lengths are equal
340342
/// @return True if raw data was set successfully, false otherwise
341-
virtual bool setRawData(const uint8_t* pRawData, int rawDataLen, timeval timestamp,
342-
LinkLayerType layerType = LINKTYPE_ETHERNET, int frameLength = -1);
343+
/// @deprecated This method does not update ownership of the pRawData pointer, inheriting the previous buffer's
344+
/// ownership. Use the overload that takes bool takeOwnership parameter for explicit control.
345+
/// @remarks Derived classes may not support using the raw data buffer directly.
346+
/// Users should not rely on the RawPacket always writing to the provided pointer location,
347+
/// and instead get the raw data pointer using getRawData().
348+
PCPP_DEPRECATED("Use the overload that takes bool takeOwnership parameter for explicit control.")
349+
bool setRawData(const uint8_t* pRawData, int rawDataLen, timeval timestamp,
350+
LinkLayerType layerType = LINKTYPE_ETHERNET, int frameLength = -1);
343351

344-
/// Set a raw data. If data was already set and deleteRawDataAtDestructor was set to 'true' the old data will be
352+
/// @brief Assign a buffer to use as raw data.
353+
///
354+
/// If the RawPacket already had raw data, it will be disposed of accordingly.
355+
///
356+
/// @param pRawData A pointer to the new raw data buffer.
357+
/// @param rawDataLen The length of the new raw data buffer in bytes.
358+
/// @param takeOwnership If true, the RawPacket will take ownership of the buffer and will be responsible for
359+
/// freeing it.
360+
/// @param timestamp The timestamp packet was received by the NIC (in usec precision).
361+
/// @param layerType The link layer type for this raw data.
362+
/// @param frameLength When reading from pcap files, sometimes the captured length is different from the
363+
/// actual packet length. This parameter represents the packet length. This parameter is optional, if not set or
364+
/// set to -1 it is assumed both lengths are equal
365+
/// @return True if raw data was set successfully, false otherwise.
366+
/// @remarks Derived classes may not support using the raw data buffer directly.
367+
/// Users should not rely on the RawPacket always writing to the provided pointer location,
368+
/// and instead get the raw data pointer using getRawData().
369+
bool setRawData(const uint8_t* pRawData, int rawDataLen, bool takeOwnership, timeval timestamp,
370+
LinkLayerType layerType = LINKTYPE_ETHERNET, int frameLength = -1);
371+
372+
/// Set a raw data. If data was already set and takeOwnership was set to 'true' the old data will be
345373
/// freed first
346374
/// @param[in] pRawData A pointer to the new raw data
347375
/// @param[in] rawDataLen The new raw data length in bytes
@@ -351,8 +379,34 @@ namespace pcpp
351379
/// actual packet length. This parameter represents the packet length. This parameter is optional, if not set or
352380
/// set to -1 it is assumed both lengths are equal
353381
/// @return True if raw data was set successfully, false otherwise
354-
virtual bool setRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp,
355-
LinkLayerType layerType = LINKTYPE_ETHERNET, int frameLength = -1);
382+
/// @deprecated This method does not update ownership of the pRawData pointer, inheriting the previous buffer's
383+
/// ownership. Use the overload that takes bool takeOwnership parameter for explicit control.
384+
/// @remarks Derived classes may not support using the raw data buffer directly.
385+
/// Users should not rely on the RawPacket always writing to the provided pointer location,
386+
/// and instead get the raw data pointer using getRawData().
387+
PCPP_DEPRECATED("Use the overload that takes bool takeOwnership parameter for explicit control.")
388+
bool setRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp,
389+
LinkLayerType layerType = LINKTYPE_ETHERNET, int frameLength = -1);
390+
391+
/// @brief Assign a buffer to use as raw data.
392+
///
393+
/// If the RawPacket already had raw data, it will be disposed of accordingly.
394+
///
395+
/// @param pRawData A pointer to the new raw data buffer.
396+
/// @param rawDataLen The length of the new raw data buffer in bytes.
397+
/// @param takeOwnership If true, the RawPacket will take ownership of the buffer and will be responsible for
398+
/// freeing it.
399+
/// @param timestamp The timestamp packet was received by the NIC (in nsec precision).
400+
/// @param layerType The link layer type for this raw data.
401+
/// @param frameLength When reading from pcap files, sometimes the captured length is different from the
402+
/// actual packet length. This parameter represents the packet length. This parameter is optional, if not set or
403+
/// set to -1 it is assumed both lengths are equal
404+
/// @return True if raw data was set successfully, false otherwise.
405+
/// @remarks Derived classes may not support using the raw data buffer directly.
406+
/// Users should not rely on the RawPacket always writing to the provided pointer location,
407+
/// and instead get the raw data pointer using getRawData().
408+
bool setRawData(const uint8_t* pRawData, int rawDataLen, bool takeOwnership, timespec timestamp,
409+
LinkLayerType layerType = LINKTYPE_ETHERNET, int frameLength = -1);
356410

357411
/// Initialize a raw packet with data. The main difference between this method and setRawData() is that
358412
/// setRawData() is meant for replacing the data in an existing raw packet, whereas this method is meant to be
@@ -362,6 +416,8 @@ namespace pcpp
362416
/// @param timestamp The timestamp packet was received by the NIC (in nsec precision)
363417
/// @param layerType The link layer type for this raw data
364418
/// @return True if raw data was set successfully, false otherwise
419+
/// @deprecated Prefer using setRawData() with takeOwnership `false`.
420+
PCPP_DEPRECATED("Prefer using setRawData() with takeOwnership `false`.")
365421
bool initWithRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp,
366422
LinkLayerType layerType = LINKTYPE_ETHERNET);
367423

@@ -424,7 +480,7 @@ namespace pcpp
424480
}
425481

426482
/// Clears all members of this instance, meaning setting raw data to nullptr, raw data length to 0, etc.
427-
/// Frees the raw data if deleteRawDataAtDestructor was set to 'true'
483+
/// Frees the raw data if takeOwnership was set to 'true'
428484
/// @todo set timestamp to a default value as well
429485
virtual void clear();
430486

@@ -461,6 +517,11 @@ namespace pcpp
461517
/// allocate the memory
462518
/// @return True if data was reallocated successfully, false otherwise
463519
virtual bool reallocateData(size_t newBufferLength);
520+
521+
protected:
522+
// Updates the raw data buffer and related members. Used by setRawData() methods.
523+
virtual bool doSetRawData(const uint8_t* pRawData, int rawDataLen, bool takeOwnership, timespec timestamp,
524+
LinkLayerType layerType, int frameLength);
464525
};
465526

466527
} // namespace pcpp

Packet++/src/RawPacket.cpp

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,15 @@
77

88
namespace pcpp
99
{
10-
RawPacket::RawPacket(const uint8_t* pRawData, int rawDataLen, timeval timestamp, bool deleteRawDataAtDestructor,
10+
RawPacket::RawPacket(const uint8_t* pRawData, int rawDataLen, timeval timestamp, bool takeOwnership,
1111
LinkLayerType layerType)
12-
: RawPacket(pRawData, rawDataLen, internal::toTimespec(timestamp), deleteRawDataAtDestructor, layerType)
12+
: RawPacket(pRawData, rawDataLen, internal::toTimespec(timestamp), takeOwnership, layerType)
1313
{}
1414

15-
RawPacket::RawPacket(const uint8_t* pRawData, int rawDataLen, timespec timestamp, bool deleteRawDataAtDestructor,
15+
RawPacket::RawPacket(const uint8_t* pRawData, int rawDataLen, timespec timestamp, bool takeOwnership,
1616
LinkLayerType layerType)
1717
: m_RawData(const_cast<uint8_t*>(pRawData)), m_RawDataLen(rawDataLen), m_FrameLength(rawDataLen),
18-
m_TimeStamp(timestamp), m_DeleteRawDataAtDestructor(deleteRawDataAtDestructor), m_RawPacketSet(true),
19-
m_LinkLayerType(layerType)
18+
m_TimeStamp(timestamp), m_OwnsRawData(takeOwnership), m_RawPacketSet(true), m_LinkLayerType(layerType)
2019
{}
2120

2221
RawPacket::~RawPacket()
@@ -56,7 +55,7 @@ namespace pcpp
5655

5756
if (allocateData)
5857
{
59-
m_DeleteRawDataAtDestructor = true;
58+
m_OwnsRawData = true;
6059
m_RawData = new uint8_t[other.m_RawDataLen];
6160
m_RawDataLen = other.m_RawDataLen;
6261
}
@@ -70,14 +69,41 @@ namespace pcpp
7069
bool RawPacket::setRawData(const uint8_t* pRawData, int rawDataLen, timeval timestamp, LinkLayerType layerType,
7170
int frameLength)
7271
{
72+
DISABLE_WARNING_PUSH;
73+
DISABLE_WARNING_DEPRECATED;
74+
7375
return setRawData(pRawData, rawDataLen, internal::toTimespec(timestamp), layerType, frameLength);
76+
77+
DISABLE_WARNING_POP;
78+
}
79+
80+
bool RawPacket::setRawData(const uint8_t* pRawData, int rawDataLen, bool takeOwnership, timeval timestamp,
81+
LinkLayerType layerType, int frameLength)
82+
{
83+
return setRawData(pRawData, rawDataLen, takeOwnership, internal::toTimespec(timestamp), layerType, frameLength);
7484
}
7585

7686
bool RawPacket::setRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp, LinkLayerType layerType,
7787
int frameLength)
88+
{
89+
// Legacy compatibility:
90+
// In previous versions of this method inherited the old ownership value and used it for the new buffer.
91+
// To keep backward compatibility we keep the same behavior here.
92+
return doSetRawData(pRawData, rawDataLen, m_OwnsRawData, timestamp, layerType, frameLength);
93+
}
94+
95+
bool RawPacket::setRawData(const uint8_t* pRawData, int rawDataLen, bool takeOwnership, timespec timestamp,
96+
LinkLayerType layerType, int frameLength)
97+
{
98+
return doSetRawData(pRawData, rawDataLen, takeOwnership, timestamp, layerType, frameLength);
99+
}
100+
101+
bool RawPacket::doSetRawData(const uint8_t* pRawData, int rawDataLen, bool takeOwnership, timespec timestamp,
102+
LinkLayerType layerType, int frameLength)
78103
{
79104
clear();
80105

106+
m_OwnsRawData = takeOwnership;
81107
m_FrameLength = (frameLength == -1) ? rawDataLen : frameLength;
82108
m_RawData = (uint8_t*)pRawData;
83109
m_RawDataLen = rawDataLen;
@@ -90,13 +116,12 @@ namespace pcpp
90116
bool RawPacket::initWithRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp,
91117
LinkLayerType layerType)
92118
{
93-
m_DeleteRawDataAtDestructor = false;
94-
return setRawData(pRawData, rawDataLen, timestamp, layerType);
119+
return setRawData(pRawData, rawDataLen, false, timestamp, layerType);
95120
}
96121

97122
void RawPacket::clear()
98123
{
99-
if (m_RawData != nullptr && m_DeleteRawDataAtDestructor)
124+
if (m_RawData != nullptr && m_OwnsRawData)
100125
delete[] m_RawData;
101126

102127
m_RawData = nullptr;
@@ -144,10 +169,10 @@ namespace pcpp
144169
uint8_t* newBuffer = new uint8_t[newBufferLength];
145170
memset(newBuffer, 0, newBufferLength);
146171
memcpy(newBuffer, m_RawData, m_RawDataLen);
147-
if (m_DeleteRawDataAtDestructor)
172+
if (m_OwnsRawData)
148173
delete[] m_RawData;
149174

150-
m_DeleteRawDataAtDestructor = true;
175+
m_OwnsRawData = true;
151176
m_RawData = newBuffer;
152177

153178
return true;

Pcap++/header/MBufRawPacket.h

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ namespace pcpp
4141
/// create a linked list of mbufs. This is good for Jumbo packets or other uses. MBufRawPacket doesn't support
4242
/// this capability so there is no way to access the mbufs linked to the mbuf wrapped by MBufRawPacket
4343
/// instance. I hope I'll be able to add this support in the future
44+
/// - Currently class methods like MBufRawPacket::setRawData() always copy the data into the mbuf data area.
45+
/// The class does not support referencing and modifying data in an external buffer like RawPacket does.
4446
class MBufRawPacket : public RawPacket
4547
{
4648
friend class DpdkDevice;
@@ -65,7 +67,7 @@ namespace pcpp
6567
/// an empty c'tor)
6668
MBufRawPacket() : RawPacket(), m_MBuf(nullptr), m_Mempool(nullptr), m_MbufDataSize(0), m_FreeMbuf(true)
6769
{
68-
m_DeleteRawDataAtDestructor = false;
70+
m_OwnsRawData = false;
6971
}
7072

7173
/// A d'tor for this class. Once called it frees the mbuf attached to it (returning it back to the mbuf pool it
@@ -147,24 +149,6 @@ namespace pcpp
147149
/// @return A pointer to the new MBufRawPacket object which is a clone of this object
148150
MBufRawPacket* clone() const override;
149151

150-
/// Set raw data to the mbuf by copying the data to it. In order to stay compatible with the ancestor method
151-
/// which takes control of the data pointer and frees it when RawPacket is destroyed, this method frees this
152-
/// pointer right away after data is copied to the mbuf. So when using this method please notice that after it's
153-
/// called pRawData memory is free, don't use this pointer again. In addition, if raw packet isn't initialized
154-
/// (mbuf is nullptr), this method will call the init() method
155-
/// @param[in] pRawData A pointer to the new raw data
156-
/// @param[in] rawDataLen The new raw data length in bytes
157-
/// @param[in] timestamp The timestamp packet was received by the NIC
158-
/// @param[in] layerType The link layer type for this raw data. Default is Ethernet
159-
/// @param[in] frameLength When reading from pcap files, sometimes the captured length is different from the
160-
/// actual packet length. This parameter represents the packet length. This parameter is optional, if not set or
161-
/// set to -1 it is assumed both lengths are equal
162-
/// @return True if raw data was copied to the mbuf successfully, false if rawDataLen is larger than mbuf max
163-
/// size, if initialization failed or if copying the data to the mbuf failed. In all of these cases an error
164-
/// will be printed to log
165-
bool setRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp,
166-
LinkLayerType layerType = LINKTYPE_ETHERNET, int frameLength = -1) override;
167-
168152
/// Clears the object and frees the mbuf
169153
void clear() override;
170154

@@ -207,6 +191,27 @@ namespace pcpp
207191
{
208192
m_FreeMbuf = val;
209193
}
194+
195+
protected:
196+
/// Set raw data to the mbuf by copying the data to it. In order to stay compatible with the ancestor method
197+
/// which takes control of the data pointer and frees it when RawPacket is destroyed, this method frees this
198+
/// pointer right away after data is copied to the mbuf. So when using this method please notice that after it's
199+
/// called pRawData memory is free, don't use this pointer again. In addition, if raw packet isn't initialized
200+
/// (mbuf is nullptr), this method will call the init() method
201+
///
202+
/// @param[in] pRawData A pointer to the new raw data
203+
/// @param[in] rawDataLen The new raw data length in bytes
204+
/// @param[in] takeOwnership Indicates whether the method should take ownership of pRawData pointer.
205+
/// @param[in] timestamp The timestamp packet was received by the NIC
206+
/// @param[in] layerType The link layer type for this raw data. Default is Ethernet
207+
/// @param[in] frameLength When reading from pcap files, sometimes the captured length is different from the
208+
/// actual packet length. This parameter represents the packet length. This parameter is optional, if not set or
209+
/// set to -1 it is assumed both lengths are equal
210+
/// @return True if raw data was copied to the mbuf successfully, false if rawDataLen is larger than mbuf max
211+
/// size, if initialization failed or if copying the data to the mbuf failed. In all of these cases an error
212+
/// will be printed to log
213+
bool doSetRawData(const uint8_t* pRawData, int rawDataLen, bool takeOwnership, timespec timestamp,
214+
LinkLayerType layerType, int frameLength) override;
210215
};
211216

212217
/// @typedef MBufRawPacketVector

0 commit comments

Comments
 (0)