+// $Id$
+//
// Copyright (C) 2007
-// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
-// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
//
// This program is free software; you can redistribute it and/or modify
namespace senf {
- /** \brief Helper baseclass implementing the PacketType interface
+ /** \brief Helper base-class implementing the PacketType interface
This helper class maybe used when building a new PacketType. It provides a complete default
implementations of this interface. To define a new PacketType, derive from this class and
static void finalize(packet p)
{
- // optionally complete the packet by generating autogenerated information
+ // optionally complete the packet by generating auto-generated information
// (like checksums)
}
\endcode
You may leave out any one of the members (you should however always define the \c
- interpreter typedef member)
+ packet typedef member)
+
+ \ingroup packet_module
*/
struct PacketTypeBase
{
///< Parser to parser packet fields
/**< This typedef has to be set to the parser of the packet
- The default is a VoidPacketParser which does not parser
+ The default is a VoidPacketParser which does not parse
any field. */
static size_type initSize();
static size_type initHeadSize();
///< Get size of new (empty) packet header
/**< This function gives the index within a newly created,
- empty packet where a subpacket is to be placed.
+ empty packet where a sub-packet is to be placed.
The default implementation returns initSize().
packet. The new packet will have a size of at least
initSize() but the size may well be larger. It is also
possible for the packet to already have further
- subpackets.
+ sub-packets.
The default implementation does nothing. */
static void dump(packet p, std::ostream & os);
///< Dump packet data in readable form
/**< The dump() function writes out a complete
- representation of the packet. This is used formost for
- debugging purposes.
+ representation of the packet. This is used for most for
+ debugging purposes.
The default implementation does nothing. */
};
/** \brief Mixin to provide standard implementations for nextPacketRange and nextPacketType
- This mixin class simplifies the definition of simple packets with fixed-size headers and/or
- trailers. For this type of Packet, this mixin provides the nextPacketRange() and
- nextPacketType() members:
+ This mixin class simplifies the definition of simple packets with fixed-size (!) headers
+ and/or trailers. For this type of Packet, this mixin provides the nextPacketRange()
+ member. If you additionally provide the optional \a Registry argument, PacketTypeMixin
+ provides a simple implementation of nextPacketType. When using the PacketTypeMixin, the
+ implementation of a packet is simplified to:
\code
+ // Here 'SomeRegistryTag' is optional
struct SimplePacketType
- : public senf::PacketTypeBase
- pyblic senf:PacketTypeMixin<SimplePacketType, SomeRegistryTag>
+ : public senf::PacketTypeBase,
+ public senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag>
{
+ typedef senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag> mixin;
+ typedef senf::ConcretePacket<SimplePacketType> packet;
+ typedef SomePacketParser parser;
+
+ using mixin::nextPacketRange;
+ // Only if the optional 'Registry' argument is provided
+ using mixin::nextPacketType;
+ // Only if using the default implementation
+ using mixin::initSize;
+ // Only if using the default implementation
+ using mixin::init;
+
static interpreter::size_type initSize()
{
// This member is optional. If it is not defined, 'senf::init_size<parser>::value'
return header_size;
}
+ static void init(packet p)
+ {
+ // This member is optional. The default implementation calls the parsers init()
+ // member.
+ }
+
static registry_key_t nextPacketKey(packet p)
{
// Return the key in the registry under which the next packet
// header is to be found. This member must be given if a Registry argument is
// passed to the PacketTypeMixin template.
- return i.fields().typeField();
+ return p->typeField();
+ }
+
+ static void finalize(packet p)
+ {
+ // Set the type field by querying the type of the next packet. This is an
+ // optional assignment: If the key is not found, the value returned by 'key'
+ // is an empty optional and the assignment will be skipped.
+ p->typeField << key(p.next(senf::nothrow));
+
+ // optionally complete the packet by generating auto-generated information
+ // (like checksums)
+ }
+
+ static void dump(packet p, std::ostream & os)
+ {
+ // Write out a readable representation of the packet for debug purposes
}
};
\endcode
+
+ Most of the members are optional, which reduces the implementation of a fixed-sized header
+ packet with no trailer and a simple next-packet header to
+
+ \code
+ struct SimplePacketType
+ : public senf::PacketTypeBase,
+ public senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag>
+ {
+ typedef senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag> mixin;
+ typedef senf::ConcretePacket<SimplePacketType> packet;
+ typedef SomePacketParser parser;
+
+ using mixin::nextPacketRange;
+ using mixin::nextPacketType;
+ using mixin::initSize;
+ using mixin::init;
+
+ static registry_key_t nextPacketKey(packet p)
+ { return p->typeField(); }
+ };
+ \endcode
+
+ If needed, you may additionally add a \c finalize() member. You also should add a \c dump()
+ member to help debugging but both members are optional.
+
+ \ingroup packet_module
*/
template <class Self, class Registry=void>
class PacketTypeMixin
{
public:
typedef typename Registry::key_t registry_key_t;
+ typedef boost::optional<registry_key_t> optional_registry_key_t;
+
+ static optional_registry_key_t key (Packet p); ///< Find key of packet from registry
+ /**< key() will query the registry to find the key of the
+ given packet. Whereas \c nextPacketKey() as implemented
+ by the mixin user will provide the registry key of the
+ next packet from information stored in the current
+ packets header, the key() member will look up the type
+ of packet \a p in the registry and return it's
+ key.
+
+ If either \a p is an in - valid() packet or the packet
+ type is not found in the registry, the returned
+ optional value will be empty. */
+
+ ///\name PacketType interface implementation
+ ///@{
static PacketInterpreterBase::optional_range nextPacketRange (Packet p);
static PacketInterpreterBase::factory_t nextPacketType (Packet p);
static PacketInterpreterBase::size_type initSize ();
static void init (Packet p);
+
+ ///@}
};
+# ifndef DOXYGEN
+
template <class Self>
class PacketTypeMixin<Self,void>
{
static void init (Packet p);
};
+# endif
+
}
///////////////////////////////hh.e////////////////////////////////////////
+#endif
+#if !defined(HH_Packets__decls_) && !defined(HH_PacketType_i_)
+#define HH_PacketType_i_
#include "PacketType.cci"
//#include "PacketType.ct"
#include "PacketType.cti"
// c-file-style: "senf"
// indent-tabs-mode: nil
// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// comment-column: 40
// End:
+