Coverage Report

Created: 2026-05-16 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Packet++/header/Packet.h
Line
Count
Source
1
#pragma once
2
3
#include "RawPacket.h"
4
#include "Layer.h"
5
#include <vector>
6
7
/// @file
8
9
/// @namespace pcpp
10
/// @brief The main namespace for the PcapPlusPlus lib
11
namespace pcpp
12
{
13
  /// @brief Options struct for configuring packet parsing behavior.
14
  ///
15
  /// The parsing options are combined. If multiple stop conditions are specified, parsing stops
16
  /// as soon as any condition is met.
17
  struct PacketParseOptions
18
  {
19
    /// @brief Defines the protocol type up to and including which the packet should be parsed (inclusive).
20
    ///
21
    /// For large packets where only the lower layers are of interest, this option can be used to limit the parsing
22
    /// procedure to the desired protocol. The packet is parsed until the specified protocol is reached and
23
    /// consumed. Layers beyond this protocol are not parsed, which can improve performance and reduce
24
    /// memory usage.
25
    ///
26
    /// @remarks If multiple consecutive layers of the same protocol type exist, parsing stops after exhausting the
27
    /// first contiguous sequence of that protocol type. This matters for protocols that may appear multiple times
28
    /// in succession within a packet (e.g. BgpLayer).
29
    ProtocolTypeFamily parseUntilProtocol = UnknownProtocol;
30
31
    /// @brief Defines an OSI model layer up to and including which the packet should be parsed (inclusive).
32
    ///
33
    /// For large packets where only the lower layers are of interest, this option can be used to limit the parsing
34
    /// procedure to the desired OSI layer. The packet is parsed until all layers belonging to the specified OSI
35
    /// layer are consumed. Layers beyond that are ignored, which can improve performance and reduce memory usage.
36
    OsiModelLayer parseUntilLayer = OsiModelLayerUnknown;
37
  };
38
39
  /// @class Packet
40
  /// This class represents a parsed packet. It contains the raw data (RawPacket instance), and a linked list of
41
  /// layers, each layer is a parsed protocol that this packet contains. The layers linked list is ordered where the
42
  /// first layer is the lowest in the packet (currently it's always Ethernet protocol as PcapPlusPlus supports only
43
  /// Ethernet packets), the next layer will be L2.5 or L3 (e.g VLAN, IPv4, IPv6, etc.), and so on. etc.), etc. The
44
  /// last layer in the linked list will be the highest in the packet. For example: for a standard HTTP request packet
45
  /// the layer will look like this: EthLayer -> IPv4Layer -> TcpLayer -> HttpRequestLayer <BR> Packet instance isn't
46
  /// read only. The user can add or remove layers, update current layer, etc.
47
  class Packet
48
  {
49
    friend class Layer;
50
51
  private:
52
    RawPacket* m_RawPacket;
53
    Layer* m_FirstLayer;
54
    Layer* m_LastLayer;
55
    size_t m_MaxPacketLen;
56
    bool m_FreeRawPacket;
57
    bool m_CanReallocateData;
58
59
  public:
60
    /// A constructor for creating a new packet (with no layers).
61
    /// When using this constructor an empty raw buffer is allocated (with the size of maxPacketLen) and a new
62
    /// RawPacket is created
63
    /// @param[in] maxPacketLen The expected packet length in bytes
64
    /// @param[in] linkType The link type to use for this packet (the default is Ethernet)
65
    explicit Packet(size_t maxPacketLen = 1, LinkLayerType linkType = LINKTYPE_ETHERNET);
66
67
    /// A constructor for creating a new packet with a buffer that is pre-allocated by the user.
68
    /// The packet is created empty (with no layers), which means the constructor doesn't parse the data in the
69
    /// buffer. Instead, all of the raw data of this packet it written to this buffer: whenever a layer is added,
70
    /// it's data is written to this buffer. The buffer isn't freed and it's content isn't erased when the packet
71
    /// object is deleted. This constructor is useful when you already have a memory buffer and you want to create
72
    /// packet data in it.
73
    /// @param[in] buffer A pointer to a pre-allocated memory buffer
74
    /// @param[in] bufferSize The size of the buffer
75
    /// @param[in] linkType The link type to use for this packet (the default is Ethernet)
76
    Packet(uint8_t* buffer, size_t bufferSize, LinkLayerType linkType = LINKTYPE_ETHERNET);
77
78
    /// A constructor for creating a packet out of already allocated RawPacket. Very useful when parsing packets
79
    /// that came from the network. When using this constructor a pointer to the RawPacket is saved (data isn't
80
    /// copied) and the RawPacket is parsed, meaning all layers are created and linked to each other in the right
81
    /// order. In this overload of the constructor the user can specify whether to free the instance of raw packet
82
    /// when the Packet is free or not
83
    /// @param[in] rawPacket A pointer to the raw packet
84
    /// @param[in] freeRawPacket Optional parameter. A flag indicating if the destructor should also call the raw
85
    /// packet destructor or not. Default value is false
86
    /// @param[in] parseUntil Optional parameter. Parse the packet until you reach a certain protocol (inclusive).
87
    /// Can be useful for cases when you need to parse only up to a certain layer and want to avoid the performance
88
    /// impact and memory consumption of parsing the whole packet. Default value is ::UnknownProtocol which means
89
    /// don't take this parameter into account
90
    /// @param[in] parseUntilLayer Optional parameter. Parse the packet until you reach a certain layer in the OSI
91
    /// model (inclusive). Can be useful for cases when you need to parse only up to a certain OSI layer (for
92
    /// example transport layer) and want to avoid the performance impact and memory consumption of parsing the
93
    /// whole packet. Default value is ::OsiModelLayerUnknown which means don't take this parameter into account
94
    explicit Packet(RawPacket* rawPacket, bool freeRawPacket = false, ProtocolType parseUntil = UnknownProtocol,
95
                    OsiModelLayer parseUntilLayer = OsiModelLayerUnknown);
96
97
    /// @copydoc Packet(RawPacket*, bool, ProtocolType, OsiModelLayer)
98
    explicit Packet(RawPacket* rawPacket, bool freeRawPacket, ProtocolTypeFamily parseUntil,
99
                    OsiModelLayer parseUntilLayer = OsiModelLayerUnknown);
100
101
    /// A constructor for creating a packet out of already allocated RawPacket. Very useful when parsing packets
102
    /// that came from the network. When using this constructor a pointer to the RawPacket is saved (data isn't
103
    /// copied) and the RawPacket is parsed, meaning all layers are created and linked to each other in the right
104
    /// order. In this overload of the constructor the user can specify whether to free the instance of raw packet
105
    /// when the Packet is free or not. This constructor should be used to parse the packet up to a certain layer
106
    /// @param[in] rawPacket A pointer to the raw packet
107
    /// @param[in] parseUntil Parse the packet until you reach a certain protocol (inclusive). Can be useful for
108
    /// cases when you need to parse only up to a certain layer and want to avoid the performance impact and memory
109
    /// consumption of parsing the whole packet
110
    explicit Packet(RawPacket* rawPacket, ProtocolType parseUntil);
111
112
    /// A constructor for creating a packet out of already allocated RawPacket. Very useful when parsing packets
113
    /// that came from the network. When using this constructor a pointer to the RawPacket is saved (data isn't
114
    /// copied) and the RawPacket is parsed, meaning all layers are created and linked to each other in the right
115
    /// order. In this overload of the constructor the user can specify whether to free the instance of raw packet
116
    /// when the Packet is free or not. This constructor should be used to parse the packet up to a certain layer
117
    /// @param[in] rawPacket A pointer to the raw packet
118
    /// @param[in] parseUntilFamily Parse the packet until you reach a certain protocol family (inclusive). Can be
119
    /// useful for cases when you need to parse only up to a certain layer and want to avoid the performance impact
120
    /// and memory consumption of parsing the whole packet
121
    explicit Packet(RawPacket* rawPacket, ProtocolTypeFamily parseUntilFamily);
122
123
    /// A constructor for creating a packet out of already allocated RawPacket. Very useful when parsing packets
124
    /// that came from the network. When using this constructor a pointer to the RawPacket is saved (data isn't
125
    /// copied) and the RawPacket is parsed, meaning all layers are created and linked to each other in the right
126
    /// order. In this overload of the constructor the user can specify whether to free the instance of raw packet
127
    /// when the Packet is free or not. This constructor should be used to parse the packet up to a certain layer in
128
    /// the OSI model
129
    /// @param[in] rawPacket A pointer to the raw packet
130
    /// @param[in] parseUntilLayer Optional parameter. Parse the packet until you reach a certain layer in the OSI
131
    /// model (inclusive). Can be useful for cases when you need to parse only up to a certain OSI layer (for
132
    /// example transport layer) and want to avoid the performance impact and memory consumption of parsing the
133
    /// whole packet
134
    explicit Packet(RawPacket* rawPacket, OsiModelLayer parseUntilLayer);
135
136
    /// A destructor for this class. Frees all layers allocated by this instance (Notice: it doesn't free layers
137
    /// that weren't allocated by this class, for example layers that were added by addLayer() or insertLayer() ).
138
    /// In addition it frees the raw packet if it was allocated by this instance (meaning if it was allocated by
139
    /// this instance constructor)
140
    virtual ~Packet()
141
1.13M
    {
142
1.13M
      destructPacketData();
143
1.13M
    }
144
145
    /// A copy constructor for this class. This copy constructor copies all the raw data and re-create all layers.
146
    /// So when the original Packet is being freed, no data will be lost in the copied instance
147
    /// @param[in] other The instance to copy from
148
    Packet(const Packet& other)
149
909k
    {
150
909k
      copyDataFrom(other);
151
909k
    }
152
153
    /// Assignment operator overloading. It first frees all layers allocated by this instance (Notice: it doesn't
154
    /// free layers that weren't allocated by this class, for example layers that were added by addLayer() or
155
    /// insertLayer() ). In addition it frees the raw packet if it was allocated by this instance (meaning if it was
156
    /// allocated by this instance constructor). Afterwards it copies the data from the other packet in the same way
157
    /// used in the copy constructor.
158
    /// @param[in] other The instance to copy from
159
    Packet& operator=(const Packet& other);
160
161
    /// Get a pointer to the Packet's RawPacket
162
    /// @return A pointer to the Packet's RawPacket
163
    RawPacket* getRawPacket() const
164
72.4k
    {
165
72.4k
      return m_RawPacket;
166
72.4k
    }
167
168
    /// Set a RawPacket and re-construct all packet layers
169
    /// @param[in] rawPacket Raw packet to set
170
    /// @param[in] freeRawPacket A flag indicating if the destructor should also call the raw packet destructor or
171
    /// not
172
    /// @param[in] parseUntil Parse the packet until it reaches this protocol. Can be useful for cases when you need
173
    /// to parse only up to a certain layer and want to avoid the performance impact and memory consumption of
174
    /// parsing the whole packet. Default value is ::UnknownProtocol which means don't take this parameter into
175
    /// account
176
    /// @param[in] parseUntilLayer Parse the packet until certain layer in OSI model. Can be useful for cases when
177
    /// you need to parse only up to a certain layer and want to avoid the performance impact and memory consumption
178
    /// of parsing the whole packet. Default value is ::OsiModelLayerUnknown which means don't take this parameter
179
    /// into account
180
    void setRawPacket(RawPacket* rawPacket, bool freeRawPacket, ProtocolTypeFamily parseUntil = UnknownProtocol,
181
                      OsiModelLayer parseUntilLayer = OsiModelLayerUnknown);
182
183
    /// @brief Parse the packet according to the provided options.
184
    ///
185
    /// The packet is parsed according to the specified options, constructing the layer hierarchy if it does not
186
    /// exist. If the packet has already been parsed, it will be re-parsed based on the new options.
187
    ///
188
    /// If @p incrementalParsing is true, the procedure will reuse existing layers where possible, only creating new
189
    /// layers for previously unparsed data. Otherwise, all existing layers are discarded and the packet is parsed
190
    /// from scratch.
191
    ///
192
    /// @param[in] options Parsing options to configure the parsing behavior.
193
    /// @param[in] incrementalParsing If 'true', incremental parsing is performed, reusing existing layers where
194
    /// possible.
195
    /// @throws std::runtime_error if there is no RawPacket associated with this Packet instance.
196
    void parsePacket(PacketParseOptions options, bool incrementalParsing = true);
197
198
    /// Get a pointer to the Packet's RawPacket in a read-only manner
199
    /// @return A pointer to the Packet's RawPacket
200
    const RawPacket* getRawPacketReadOnly() const
201
0
    {
202
0
      return m_RawPacket;
203
0
    }
204
205
    /// Get a pointer to the first (lowest) layer in the packet
206
    /// @return A pointer to the first (lowest) layer in the packet
207
    Layer* getFirstLayer() const
208
19.3M
    {
209
19.3M
      return m_FirstLayer;
210
19.3M
    }
211
212
    /// Get a pointer to the last (highest) layer in the packet
213
    /// @return A pointer to the last (highest) layer in the packet
214
    Layer* getLastLayer() const
215
0
    {
216
0
      return m_LastLayer;
217
0
    }
218
219
    /// Add a new layer as the last layer in the packet. This method gets a pointer to the new layer as a parameter
220
    /// and attaches it to the packet. Notice after calling this method the input layer is attached to the packet so
221
    /// every change you make in it affect the packet; Also it cannot be attached to other packets
222
    /// @param[in] newLayer A pointer to the new layer to be added to the packet
223
    /// @param[in] ownInPacket If true, Packet fully owns newLayer, including memory deletion upon destruct. Default
224
    /// is false.
225
    /// @return True if everything went well or false otherwise (an appropriate error log message will be printed in
226
    /// such cases)
227
    bool addLayer(Layer* newLayer, bool ownInPacket = false)
228
0
    {
229
0
      return insertLayer(m_LastLayer, newLayer, ownInPacket);
230
0
    }
231
232
    /// Insert a new layer after an existing layer in the packet. This method gets a pointer to the new layer as a
233
    /// parameter and attaches it to the packet. Notice after calling this method the input layer is attached to the
234
    /// packet so every change you make in it affect the packet; Also it cannot be attached to other packets
235
    /// @param[in] prevLayer A pointer to an existing layer in the packet which the new layer should followed by. If
236
    /// this layer isn't attached to a packet and error will be printed to log and false will be returned
237
    /// @param[in] newLayer A pointer to the new layer to be added to the packet
238
    /// @param[in] ownInPacket If true, Packet fully owns newLayer, including memory deletion upon destruct. Default
239
    /// is false.
240
    /// @return True if everything went well or false otherwise (an appropriate error log message will be printed in
241
    /// such cases)
242
    bool insertLayer(Layer* prevLayer, Layer* newLayer, bool ownInPacket = false);
243
244
    /// Remove an existing layer from the packet. The layer to removed is identified by its type (protocol). If the
245
    /// packet has multiple layers of the same type in the packet the user may specify the index of the layer to
246
    /// remove (the default index is 0 - remove the first layer of this type). If the layer was allocated during
247
    /// packet creation it will be deleted and any pointer to it will get invalid. However if the layer was
248
    /// allocated by the user and manually added to the packet it will simply get detached from the packet, meaning
249
    /// the pointer to it will stay valid and its data (that was removed from the packet) will be copied back to the
250
    /// layer. In that case it's the user's responsibility to delete the layer instance
251
    /// @param[in] layerType The layer type (protocol) to remove
252
    /// @param[in] index If there are multiple layers of the same type, indicate which instance to remove. The
253
    /// default value is 0, meaning remove the first layer of this type
254
    /// @return True if everything went well or false otherwise (an appropriate error log message will be printed in
255
    /// such cases)
256
    bool removeLayer(ProtocolType layerType, int index = 0);
257
258
    /// Remove the first layer in the packet. The layer will be deleted if it was allocated during packet creation,
259
    /// or detached if was allocated outside of the packet. Please refer to removeLayer() to get more info
260
    /// @return True if layer removed successfully, or false if removing the layer failed or if there are no layers
261
    /// in the packet. In any case of failure an appropriate error log message will be printed
262
    bool removeFirstLayer();
263
264
    /// Remove the last layer in the packet. The layer will be deleted if it was allocated during packet creation,
265
    /// or detached if was allocated outside of the packet. Please refer to removeLayer() to get more info
266
    /// @return True if layer removed successfully, or false if removing the layer failed or if there are no layers
267
    /// in the packet. In any case of failure an appropriate error log message will be printed
268
    bool removeLastLayer();
269
270
    /// Remove all layers that come after a certain layer. All layers removed will be deleted if they were allocated
271
    /// during packet creation or detached if were allocated outside of the packet, please refer to removeLayer() to
272
    /// get more info
273
    /// @param[in] layer A pointer to the layer to begin removing from. Please note this layer will not be removed,
274
    /// only the layers that come after it will be removed. Also, if removal of one layer failed, the method will
275
    /// return immediately and the following layers won't be deleted
276
    /// @return True if all layers were removed successfully, or false if failed to remove at least one layer. In
277
    /// any case of failure an appropriate error log message will be printed
278
    bool removeAllLayersAfter(Layer* layer);
279
280
    /// Detach a layer from the packet. Detaching means the layer instance will not be deleted, but rather separated
281
    /// from the packet - e.g it will be removed from the layer chain of the packet and its data will be copied from
282
    /// the packet buffer into an internal layer buffer. After a layer is detached, it can be added into another
283
    /// packet (but it's impossible to attach a layer to multiple packets in the same time). After layer is
284
    /// detached, it's the user's responsibility to delete it when it's not needed anymore
285
    /// @param[in] layerType The layer type (protocol) to detach from the packet
286
    /// @param[in] index If there are multiple layers of the same type, indicate which instance to detach. The
287
    /// default value is 0, meaning detach the first layer of this type
288
    /// @return A pointer to the detached layer or nullptr if detaching process failed. In any case of failure an
289
    /// appropriate error log message will be printed
290
    Layer* detachLayer(ProtocolType layerType, int index = 0);
291
292
    /// Detach a layer from the packet. Detaching means the layer instance will not be deleted, but rather separated
293
    /// from the packet - e.g it will be removed from the layer chain of the packet and its data will be copied from
294
    /// the packet buffer into an internal layer buffer. After a layer is detached, it can be added into another
295
    /// packet (but it's impossible to attach a layer to multiple packets at the same time). After layer is
296
    /// detached, it's the user's responsibility to delete it when it's not needed anymore
297
    /// @param[in] layer A pointer to the layer to detach
298
    /// @return True if the layer was detached successfully, or false if something went wrong. In any case of
299
    /// failure an appropriate error log message will be printed
300
    bool detachLayer(Layer* layer)
301
0
    {
302
0
      return removeLayer(layer, false);
303
0
    }
304
305
    /// Get a pointer to the layer of a certain type (protocol). This method goes through the layers and returns a
306
    /// layer that matches the give protocol type
307
    /// @param[in] layerType The layer type (protocol) to fetch
308
    /// @param[in] index If there are multiple layers of the same type, indicate which instance to fetch. The
309
    /// default value is 0, meaning fetch the first layer of this type
310
    /// @return A pointer to the layer or nullptr if no such layer was found
311
    Layer* getLayerOfType(ProtocolType layerType, int index = 0) const;
312
313
    /// A templated method to get a layer of a certain type (protocol). If no layer of such type is found, nullptr
314
    /// is returned
315
    /// @param[in] reverseOrder The optional parameter that indicates that the lookup should run in reverse order,
316
    /// the default value is false
317
    /// @return A pointer to the layer of the requested type, nullptr if not found
318
    template <class TLayer> TLayer* getLayerOfType(bool reverseOrder = false) const;
319
320
    /// A templated method to get the first layer of a certain type (protocol), start searching from a certain
321
    /// layer. For example: if a packet looks like: EthLayer -> VlanLayer(1) -> VlanLayer(2) -> VlanLayer(3) ->
322
    /// IPv4Layer and the user put VlanLayer(2) as a parameter and wishes to search for a VlanLayer, VlanLayer(3)
323
    /// will be returned If no layer of such type is found, nullptr is returned
324
    /// @param[in] startLayer A pointer to the layer to start search from
325
    /// @return A pointer to the layer of the requested type, nullptr if not found
326
    template <class TLayer> TLayer* getNextLayerOfType(Layer* startLayer) const;
327
328
    /// A templated method to get the first layer of a certain type (protocol), start searching from a certain
329
    /// layer. For example: if a packet looks like: EthLayer -> VlanLayer(1) -> VlanLayer(2) -> VlanLayer(3) ->
330
    /// IPv4Layer and the user put VlanLayer(2) as a parameter and wishes to search for a VlanLayer, VlanLayer(1)
331
    /// will be returned If no layer of such type is found, nullptr is returned
332
    /// @param[in] startLayer A pointer to the layer to start search from
333
    /// @return A pointer to the layer of the requested type, nullptr if not found
334
    template <class TLayer> TLayer* getPrevLayerOfType(Layer* startLayer) const;
335
336
    /// Check whether the packet contains a layer of a certain protocol
337
    /// @param[in] protocolType The protocol type to search
338
    /// @return True if the packet contains a layer of a certain protocol, false otherwise
339
    bool isPacketOfType(ProtocolType protocolType) const;
340
341
    /// Check whether the packet contains a layer of a certain protocol family
342
    /// @param[in] protocolTypeFamily The protocol type family to search
343
    /// @return True if the packet contains a layer of a certain protocol family, false otherwise
344
    bool isPacketOfType(ProtocolTypeFamily protocolTypeFamily) const;
345
346
    /// Each layer can have fields that can be calculate automatically from other fields using
347
    /// Layer#computeCalculateFields(). This method forces all layers to calculate these fields values
348
    void computeCalculateFields();
349
350
    /// Each layer can print a string representation of the layer most important data using Layer#toString(). This
351
    /// method aggregates this string from all layers and print it to a complete string containing all packet's
352
    /// relevant data
353
    /// @param[in] timeAsLocalTime Print time as local time or GMT. Default (true value) is local time, for GMT set
354
    /// to false
355
    /// @return A string containing most relevant data from all layers (looks like the packet description in
356
    /// Wireshark)
357
    std::string toString(bool timeAsLocalTime = true) const;
358
359
    /// Similar to toString(), but instead of one string it outputs a list of strings, one string for every layer
360
    /// @param[out] result A string vector that will contain all strings
361
    /// @param[in] timeAsLocalTime Print time as local time or GMT. Default (true value) is local time, for GMT set
362
    /// to false
363
    void toStringList(std::vector<std::string>& result, bool timeAsLocalTime = true) const;
364
365
  private:
366
    void copyDataFrom(const Packet& other);
367
368
    void destructPacketData();
369
    void destroyAllLayers();
370
371
    bool extendLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToExtend);
372
    bool shortenLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToShorten);
373
374
    void reallocateRawData(size_t newSize);
375
376
    bool removeLayer(Layer* layer, bool tryToDelete);
377
378
    std::string printPacketInfo(bool timeAsLocalTime) const;
379
380
    Layer* createFirstLayer(LinkLayerType linkType);
381
382
    template <typename TLayer, typename NextLayerFn>
383
    static TLayer* searchLayerStackForType(Layer* startLayer, NextLayerFn nextLayerFn, bool skipFirst);
384
  };  // class Packet
385
386
  // implementation of inline methods
387
388
  template <class TLayer> TLayer* Packet::getLayerOfType(bool reverse) const
389
7.24k
  {
390
7.24k
    if (!reverse)
391
7.24k
    {
392
7.24k
      return searchLayerStackForType<TLayer>(
393
7.24k
          m_FirstLayer, [](Layer* layer) { return layer->getNextLayer(); }, false);
Unexecuted instantiation: pcpp::Packet::getLayerOfType<pcpp::TcpLayer>(bool) const::{lambda(pcpp::Layer*)#1}::operator()(pcpp::Layer*) const
Unexecuted instantiation: pcpp::Packet::getLayerOfType<pcpp::UdpLayer>(bool) const::{lambda(pcpp::Layer*)#1}::operator()(pcpp::Layer*) const
Unexecuted instantiation: pcpp::Packet::getLayerOfType<pcpp::IPv4Layer>(bool) const::{lambda(pcpp::Layer*)#1}::operator()(pcpp::Layer*) const
Unexecuted instantiation: pcpp::Packet::getLayerOfType<pcpp::IPv6Layer>(bool) const::{lambda(pcpp::Layer*)#1}::operator()(pcpp::Layer*) const
pcpp::Packet::getLayerOfType<pcpp::IPLayer>(bool) const::{lambda(pcpp::Layer*)#1}::operator()(pcpp::Layer*) const
Line
Count
Source
393
7.24k
          m_FirstLayer, [](Layer* layer) { return layer->getNextLayer(); }, false);
394
7.24k
    }
395
396
    // lookup in reverse order
397
0
    return searchLayerStackForType<TLayer>(m_LastLayer, [](Layer* layer) { return layer->getPrevLayer(); }, false);
Unexecuted instantiation: pcpp::Packet::getLayerOfType<pcpp::TcpLayer>(bool) const::{lambda(pcpp::Layer*)#2}::operator()(pcpp::Layer*) const
Unexecuted instantiation: pcpp::Packet::getLayerOfType<pcpp::UdpLayer>(bool) const::{lambda(pcpp::Layer*)#2}::operator()(pcpp::Layer*) const
Unexecuted instantiation: pcpp::Packet::getLayerOfType<pcpp::IPv4Layer>(bool) const::{lambda(pcpp::Layer*)#2}::operator()(pcpp::Layer*) const
Unexecuted instantiation: pcpp::Packet::getLayerOfType<pcpp::IPv6Layer>(bool) const::{lambda(pcpp::Layer*)#2}::operator()(pcpp::Layer*) const
Unexecuted instantiation: pcpp::Packet::getLayerOfType<pcpp::IPLayer>(bool) const::{lambda(pcpp::Layer*)#2}::operator()(pcpp::Layer*) const
398
7.24k
  }
Unexecuted instantiation: pcpp::TcpLayer* pcpp::Packet::getLayerOfType<pcpp::TcpLayer>(bool) const
Unexecuted instantiation: pcpp::UdpLayer* pcpp::Packet::getLayerOfType<pcpp::UdpLayer>(bool) const
Unexecuted instantiation: pcpp::IPv4Layer* pcpp::Packet::getLayerOfType<pcpp::IPv4Layer>(bool) const
Unexecuted instantiation: pcpp::IPv6Layer* pcpp::Packet::getLayerOfType<pcpp::IPv6Layer>(bool) const
pcpp::IPLayer* pcpp::Packet::getLayerOfType<pcpp::IPLayer>(bool) const
Line
Count
Source
389
7.24k
  {
390
7.24k
    if (!reverse)
391
7.24k
    {
392
7.24k
      return searchLayerStackForType<TLayer>(
393
7.24k
          m_FirstLayer, [](Layer* layer) { return layer->getNextLayer(); }, false);
394
7.24k
    }
395
396
    // lookup in reverse order
397
0
    return searchLayerStackForType<TLayer>(m_LastLayer, [](Layer* layer) { return layer->getPrevLayer(); }, false);
398
7.24k
  }
399
400
  template <class TLayer> TLayer* Packet::getNextLayerOfType(Layer* curLayer) const
401
  {
402
    return searchLayerStackForType<TLayer>(curLayer, [](Layer* layer) { return layer->getNextLayer(); }, true);
403
  }
404
405
  template <class TLayer> TLayer* Packet::getPrevLayerOfType(Layer* curLayer) const
406
  {
407
    return searchLayerStackForType<TLayer>(curLayer, [](Layer* layer) { return layer->getPrevLayer(); }, true);
408
  }
409
410
  template <typename TLayer, typename NextLayerFn>
411
  TLayer* Packet::searchLayerStackForType(Layer* curLayer, NextLayerFn nextLayerFn, bool skipFirst)
412
7.24k
  {
413
7.24k
    if (curLayer == nullptr)
414
0
      return nullptr;
415
416
7.24k
    if (skipFirst)
417
0
    {
418
0
      curLayer = nextLayerFn(curLayer);
419
0
    }
420
421
14.4k
    while (curLayer != nullptr)
422
14.4k
    {
423
14.4k
      auto* curLayerCasted = dynamic_cast<TLayer*>(curLayer);
424
14.4k
      if (curLayerCasted != nullptr)
425
7.24k
        return curLayerCasted;
426
427
7.24k
      curLayer = nextLayerFn(curLayer);
428
7.24k
    }
429
430
0
    return nullptr;
431
7.24k
  }
Unexecuted instantiation: pcpp::TcpLayer* pcpp::Packet::searchLayerStackForType<pcpp::TcpLayer, pcpp::Packet::getLayerOfType<pcpp::TcpLayer>(bool) const::{lambda(pcpp::Layer*)#1}>(pcpp::Layer*, pcpp::Packet::getLayerOfType<pcpp::TcpLayer>(bool) const::{lambda(pcpp::Layer*)#1}, bool)
Unexecuted instantiation: pcpp::TcpLayer* pcpp::Packet::searchLayerStackForType<pcpp::TcpLayer, pcpp::Packet::getLayerOfType<pcpp::TcpLayer>(bool) const::{lambda(pcpp::Layer*)#2}>(pcpp::Layer*, pcpp::Packet::getLayerOfType<pcpp::TcpLayer>(bool) const::{lambda(pcpp::Layer*)#2}, bool)
Unexecuted instantiation: pcpp::UdpLayer* pcpp::Packet::searchLayerStackForType<pcpp::UdpLayer, pcpp::Packet::getLayerOfType<pcpp::UdpLayer>(bool) const::{lambda(pcpp::Layer*)#1}>(pcpp::Layer*, pcpp::Packet::getLayerOfType<pcpp::UdpLayer>(bool) const::{lambda(pcpp::Layer*)#1}, bool)
Unexecuted instantiation: pcpp::UdpLayer* pcpp::Packet::searchLayerStackForType<pcpp::UdpLayer, pcpp::Packet::getLayerOfType<pcpp::UdpLayer>(bool) const::{lambda(pcpp::Layer*)#2}>(pcpp::Layer*, pcpp::Packet::getLayerOfType<pcpp::UdpLayer>(bool) const::{lambda(pcpp::Layer*)#2}, bool)
Unexecuted instantiation: pcpp::IPv4Layer* pcpp::Packet::searchLayerStackForType<pcpp::IPv4Layer, pcpp::Packet::getLayerOfType<pcpp::IPv4Layer>(bool) const::{lambda(pcpp::Layer*)#1}>(pcpp::Layer*, pcpp::Packet::getLayerOfType<pcpp::IPv4Layer>(bool) const::{lambda(pcpp::Layer*)#1}, bool)
Unexecuted instantiation: pcpp::IPv4Layer* pcpp::Packet::searchLayerStackForType<pcpp::IPv4Layer, pcpp::Packet::getLayerOfType<pcpp::IPv4Layer>(bool) const::{lambda(pcpp::Layer*)#2}>(pcpp::Layer*, pcpp::Packet::getLayerOfType<pcpp::IPv4Layer>(bool) const::{lambda(pcpp::Layer*)#2}, bool)
Unexecuted instantiation: pcpp::IPv6Layer* pcpp::Packet::searchLayerStackForType<pcpp::IPv6Layer, pcpp::Packet::getLayerOfType<pcpp::IPv6Layer>(bool) const::{lambda(pcpp::Layer*)#1}>(pcpp::Layer*, pcpp::Packet::getLayerOfType<pcpp::IPv6Layer>(bool) const::{lambda(pcpp::Layer*)#1}, bool)
Unexecuted instantiation: pcpp::IPv6Layer* pcpp::Packet::searchLayerStackForType<pcpp::IPv6Layer, pcpp::Packet::getLayerOfType<pcpp::IPv6Layer>(bool) const::{lambda(pcpp::Layer*)#2}>(pcpp::Layer*, pcpp::Packet::getLayerOfType<pcpp::IPv6Layer>(bool) const::{lambda(pcpp::Layer*)#2}, bool)
pcpp::IPLayer* pcpp::Packet::searchLayerStackForType<pcpp::IPLayer, pcpp::Packet::getLayerOfType<pcpp::IPLayer>(bool) const::{lambda(pcpp::Layer*)#1}>(pcpp::Layer*, pcpp::Packet::getLayerOfType<pcpp::IPLayer>(bool) const::{lambda(pcpp::Layer*)#1}, bool)
Line
Count
Source
412
7.24k
  {
413
7.24k
    if (curLayer == nullptr)
414
0
      return nullptr;
415
416
7.24k
    if (skipFirst)
417
0
    {
418
0
      curLayer = nextLayerFn(curLayer);
419
0
    }
420
421
14.4k
    while (curLayer != nullptr)
422
14.4k
    {
423
14.4k
      auto* curLayerCasted = dynamic_cast<TLayer*>(curLayer);
424
14.4k
      if (curLayerCasted != nullptr)
425
7.24k
        return curLayerCasted;
426
427
7.24k
      curLayer = nextLayerFn(curLayer);
428
7.24k
    }
429
430
0
    return nullptr;
431
7.24k
  }
Unexecuted instantiation: pcpp::IPLayer* pcpp::Packet::searchLayerStackForType<pcpp::IPLayer, pcpp::Packet::getLayerOfType<pcpp::IPLayer>(bool) const::{lambda(pcpp::Layer*)#2}>(pcpp::Layer*, pcpp::Packet::getLayerOfType<pcpp::IPLayer>(bool) const::{lambda(pcpp::Layer*)#2}, bool)
432
433
  inline std::ostream& operator<<(std::ostream& os, const pcpp::Packet& packet)
434
0
  {
435
0
    os << packet.toString();
436
0
    return os;
437
0
  }
438
}  // namespace pcpp