@@ -264,6 +264,22 @@ namespace pcpp
264264 return m_NextLayer != nullptr ;
265265 }
266266
267+ // / @brief Construct the next layer in the protocol stack. No validation is performed on the data.
268+ // /
269+ // / This overload infers the Packet from the current layer.
270+ // /
271+ // / @tparam T The type of the layer to construct
272+ // / @tparam Args The types of the arguments to pass to the layer constructor
273+ // / @param data The data to construct the layer from
274+ // / @param dataLen The length of the data
275+ // / @param extraArgs Extra arguments to be forwarded to the layer constructor
276+ // / @return The constructed layer
277+ template <typename T, typename ... Args>
278+ Layer* constructNextLayer (uint8_t * data, size_t dataLen, Args&&... extraArgs)
279+ {
280+ return constructNextLayer<T>(data, dataLen, getAttachedPacket (), std::forward<Args>(extraArgs)...);
281+ }
282+
267283 // / Construct the next layer in the protocol stack. No validation is performed on the data.
268284 // / @tparam T The type of the layer to construct
269285 // / @tparam Args The types of the arguments to pass to the layer constructor
@@ -285,6 +301,125 @@ namespace pcpp
285301 return newLayer;
286302 }
287303
304+ // / @brief Construct the next layer in the protocol stack using a factory functor.
305+ // /
306+ // / No validation is performed on the data, outside of what the factory functor may perform.
307+ // / If the factory returns a nullptr, no next layer is set.
308+ // /
309+ // / The factory functor is expected to have the following signature:
310+ // / Layer* factoryFn(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, ...);
311+ // /
312+ // / This overload infers the Packet from the current layer.
313+ // /
314+ // / @tparam TFactory The factory functor type.
315+ // / @tparam ...Args Parameter pack for extra arguments to pass to the factory functor.
316+ // / @param[in] factoryFn The factory functor to create the layer.
317+ // / @param[in] data The data to construct the layer from
318+ // / @param[in] dataLen The length of the data
319+ // / @param[in] extraArgs Extra arguments to be forwarded to the factory.
320+ // / @return The return value of the factory functor.
321+ template <typename TFactory, typename ... Args>
322+ Layer* constructNextLayerFromFactory (TFactory factoryFn, uint8_t * data, size_t dataLen, Args&&... extraArgs)
323+ {
324+ return constructNextLayerFromFactory<TFactory>(factoryFn, data, dataLen, getAttachedPacket (),
325+ std::forward<Args>(extraArgs)...);
326+ }
327+
328+ // / @brief Construct the next layer in the protocol stack using a factory functor.
329+ // /
330+ // / No validation is performed on the data, outside of what the factory functor may perform.
331+ // / If the factory returns a nullptr, no next layer is set.
332+ // /
333+ // / The factory functor is expected to have the following signature:
334+ // / Layer* factoryFn(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, ...);
335+ // /
336+ // / @tparam TFactory The factory functor type.
337+ // / @tparam ...Args Parameter pack for extra arguments to pass to the factory functor.
338+ // / @param[in] factoryFn The factory functor to create the layer.
339+ // / @param[in] data The data to construct the layer from
340+ // / @param[in] dataLen The length of the data
341+ // / @param[in] packet The packet the layer belongs to
342+ // / @param[in] extraArgs Extra arguments to be forwarded to the factory.
343+ // / @return The return value of the factory functor.
344+ template <typename TFactory, typename ... Args>
345+ Layer* constructNextLayerFromFactory (TFactory factoryFn, uint8_t * data, size_t dataLen, Packet* packet,
346+ Args&&... extraArgs)
347+ {
348+ if (hasNextLayer ())
349+ {
350+ throw std::runtime_error (" Next layer already exists" );
351+ }
352+
353+ // cppcheck-suppress redundantInitialization
354+ Layer* newLayer = factoryFn (data, dataLen, this , packet, std::forward<Args>(extraArgs)...);
355+ setNextLayer (newLayer);
356+ return newLayer;
357+ }
358+
359+ // / Try to construct the next layer in the protocol stack.
360+ // /
361+ // / This overload infers the Packet from the current layer.
362+ // /
363+ // / The method checks if the data is valid for the layer type T before constructing it by calling
364+ // / T::isDataValid(data, dataLen). If the data is invalid, no layer is constructed and a nullptr is returned.
365+ // /
366+ // / @tparam T The type of the layer to construct
367+ // / @tparam Args The types of the extra arguments to pass to the layer constructor
368+ // / @param[in] data The data to construct the layer from
369+ // / @param[in] dataLen The length of the data
370+ // / @param[in] extraArgs Extra arguments to be forwarded to the layer constructor
371+ // / @return The constructed layer or nullptr if the data is invalid
372+ template <typename T, typename ... Args>
373+ Layer* tryConstructNextLayer (uint8_t * data, size_t dataLen, Args&&... extraArgs)
374+ {
375+ return tryConstructNextLayer<T>(data, dataLen, getAttachedPacket (), std::forward<Args>(extraArgs)...);
376+ }
377+
378+ // / Try to construct the next layer in the protocol stack.
379+ // /
380+ // / The method checks if the data is valid for the layer type T before constructing it by calling
381+ // / T::isDataValid(data, dataLen). If the data is invalid, no layer is constructed and a nullptr is returned.
382+ // /
383+ // / @tparam T The type of the layer to construct
384+ // / @tparam Args The types of the extra arguments to pass to the layer constructor
385+ // / @param[in] data The data to construct the layer from
386+ // / @param[in] dataLen The length of the data
387+ // / @param[in] packet The packet the layer belongs to
388+ // / @param[in] extraArgs Extra arguments to be forwarded to the layer constructor
389+ // / @return The constructed layer or nullptr if the data is invalid
390+ template <typename T, typename ... Args>
391+ Layer* tryConstructNextLayer (uint8_t * data, size_t dataLen, Packet* packet, Args&&... extraArgs)
392+ {
393+ if (T::isDataValid (data, dataLen))
394+ {
395+ return constructNextLayer<T>(data, dataLen, packet, std::forward<Args>(extraArgs)...);
396+ }
397+ return nullptr ;
398+ }
399+
400+ // / @brief Try to construct the next layer in the protocol stack with a fallback option.
401+ // /
402+ // / This overload infers the Packet from the current layer.
403+ // /
404+ // / The method checks if the data is valid for the layer type T before constructing it by calling
405+ // / T::isDataValid(data, dataLen). If the data is invalid, it constructs the layer of type TFallback.
406+ // /
407+ // / @tparam T The type of the layer to construct
408+ // / @tparam TFallback The fallback layer type to construct if T fails
409+ // / @tparam Args The types of the extra arguments to pass to the layer constructor of T
410+ // / @param[in] data The data to construct the layer from
411+ // / @param[in] dataLen The length of the data
412+ // / @param[in] extraArgs Extra arguments to be forwarded to the layer constructor of T
413+ // / @return The constructed layer of type T or TFallback
414+ // / @remarks The parameters extraArgs are forwarded to the factory function, but not to the TFallback
415+ // / constructor.
416+ template <typename T, typename TFallback, typename ... Args>
417+ Layer* tryConstructNextLayerWithFallback (uint8_t * data, size_t dataLen, Args&&... extraArgs)
418+ {
419+ return tryConstructNextLayerWithFallback<T, TFallback>(data, dataLen, getAttachedPacket (),
420+ std::forward<Args>(extraArgs)...);
421+ }
422+
288423 // / Try to construct the next layer in the protocol stack with a fallback option.
289424 // /
290425 // / The method checks if the data is valid for the layer type T before constructing it by calling
@@ -298,6 +433,8 @@ namespace pcpp
298433 // / @param[in] packet The packet the layer belongs to
299434 // / @param[in] extraArgs Extra arguments to be forwarded to the layer constructor of T
300435 // / @return The constructed layer of type T or TFallback
436+ // / @remarks The parameters extraArgs are forwarded to the factory function, but not to the TFallback
437+ // / constructor.
301438 template <typename T, typename TFallback, typename ... Args>
302439 Layer* tryConstructNextLayerWithFallback (uint8_t * data, size_t dataLen, Packet* packet, Args&&... extraArgs)
303440 {
@@ -309,40 +446,82 @@ namespace pcpp
309446 return constructNextLayer<TFallback>(data, dataLen, packet);
310447 }
311448
312- // / @brief Check if the data is large enough to reinterpret as a type
449+ // / @brief Try to construct the next layer in the protocol stack using a factory functor with a fallback option.
313450 // /
314- // / The data must be non-null and at least as large as the type
451+ // / The method will attempt to construct the next layer using the provided factory function.
452+ // / If the factory function returns nullptr, indicating failure to create the layer, the method will then
453+ // / construct a layer of type TFallback.
315454 // /
316- // / @tparam T The type to reinterpret as
317- // / @param data The data to check
318- // / @param dataLen The length of the data
319- // / @return True if the data is large enough to reinterpret as T, false otherwise
320- template <typename T> static bool canReinterpretAs (const uint8_t * data, size_t dataLen)
455+ // / The factory functor is expected to have the following signature:
456+ // / Layer* factoryFn(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, ...);
457+ // /
458+ // / This overload infers the Packet from the current layer.
459+ // /
460+ // / @tparam TFallback The fallback layer type to construct if the factory fails.
461+ // / @tparam TFactory The factory functor type.
462+ // / @tparam ...Args Parameter pack for extra arguments to pass to the factory functor.
463+ // / @param[in] factoryFn The factory functor to create the layer.
464+ // / @param[in] data The data to construct the layer from
465+ // / @param[in] dataLen The length of the data
466+ // / @param[in] extraArgs Extra arguments to be forwarded to the factory.
467+ // / @return The return value of the factory functor.
468+ // / @remarks The parameters extraArgs are forwarded to the factory function, but not to the TFallback
469+ // / constructor.
470+ template <typename TFallback, typename TFactory, typename ... Args>
471+ Layer* tryConstructNextLayerFromFactoryWithFallback (TFactory factoryFn, uint8_t * data, size_t dataLen,
472+ Args&&... extraArgs)
321473 {
322- return data != nullptr && dataLen >= sizeof (T);
474+ // Note that the fallback is first to allow template argument deduction of the factory type.
475+ return tryConstructNextLayerFromFactoryWithFallback<TFallback, TFactory>(
476+ factoryFn, data, dataLen, getAttachedPacket (), std::forward<Args>(extraArgs)...);
323477 }
324478
325- private:
326- // / Try to construct the next layer in the protocol stack.
479+ // / @brief Try to construct the next layer in the protocol stack using a factory functor with a fallback option.
327480 // /
328- // / The method checks if the data is valid for the layer type T before constructing it by calling
329- // / T::isDataValid(data, dataLen). If the data is invalid, a nullptr is returned.
481+ // / The method will attempt to construct the next layer using the provided factory function.
482+ // / If the factory function returns nullptr, indicating failure to create the layer, the method will then
483+ // / construct a layer of type TFallback.
330484 // /
331- // / @tparam T The type of the layer to construct
332- // / @tparam Args The types of the extra arguments to pass to the layer constructor
485+ // / The factory functor is expected to have the following signature:
486+ // / Layer* factoryFn(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, ...);
487+ // /
488+ // / @tparam TFallback The fallback layer type to construct if the factory fails.
489+ // / @tparam TFactory The factory functor type.
490+ // / @tparam ...Args Parameter pack for extra arguments to pass to the factory functor.
491+ // / @param[in] factoryFn The factory functor to create the layer.
333492 // / @param[in] data The data to construct the layer from
334493 // / @param[in] dataLen The length of the data
335494 // / @param[in] packet The packet the layer belongs to
336- // / @param[in] extraArgs Extra arguments to be forwarded to the layer constructor
337- // / @return The constructed layer or nullptr if the data is invalid
338- template <typename T, typename ... Args>
339- Layer* tryConstructNextLayer (uint8_t * data, size_t dataLen, Packet* packet, Args&&... extraArgs)
495+ // / @param[in] extraArgs Extra arguments to be forwarded to the factory.
496+ // / @return The return value of the factory functor.
497+ // / @remarks The parameters extraArgs are forwarded to the factory function, but not to the TFallback
498+ // / constructor.
499+ template <typename TFallback, typename TFactory, typename ... Args>
500+ Layer* tryConstructNextLayerFromFactoryWithFallback (TFactory factoryFn, uint8_t * data, size_t dataLen,
501+ Packet* packet, Args&&... extraArgs)
340502 {
341- if (T::isDataValid (data, dataLen))
503+ auto nextLayer = constructNextLayerFromFactory<TFactory>(factoryFn, data, dataLen, packet,
504+ std::forward<Args>(extraArgs)...);
505+ if (nextLayer != nullptr )
342506 {
343- return constructNextLayer<T>(data, dataLen, packet, std::forward<Args>(extraArgs)...) ;
507+ return nextLayer ;
344508 }
345- return nullptr ;
509+
510+ // factory failed, construct fallback layer
511+ return constructNextLayer<TFallback>(data, dataLen, packet);
512+ }
513+
514+ // / @brief Check if the data is large enough to reinterpret as a type
515+ // /
516+ // / The data must be non-null and at least as large as the type
517+ // /
518+ // / @tparam T The type to reinterpret as
519+ // / @param data The data to check
520+ // / @param dataLen The length of the data
521+ // / @return True if the data is large enough to reinterpret as T, false otherwise
522+ template <typename T> static bool canReinterpretAs (const uint8_t * data, size_t dataLen)
523+ {
524+ return data != nullptr && dataLen >= sizeof (T);
346525 }
347526 };
348527
0 commit comments