X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Packets%2F80221Bundle%2FTLVPacket.hh;h=4c1a5882506dac2ebc363bdf55c6fc36fc6328ad;hb=f2f5d59e83863f3b513950173baee1b6da2aee3c;hp=8f9398b59abb687bbbf6f0916d33166b9341acb2;hpb=32be66071113df31a085821e31414eeb776022fa;p=senf.git diff --git a/Packets/80221Bundle/TLVPacket.hh b/Packets/80221Bundle/TLVPacket.hh index 8f9398b..4c1a588 100644 --- a/Packets/80221Bundle/TLVPacket.hh +++ b/Packets/80221Bundle/TLVPacket.hh @@ -35,19 +35,13 @@ namespace senf { - /** \brief xxx - - \todo document me - \todo add usefull exceptions strings - - */ - struct UnsuportedTLVPacketException : public senf::Exception - { UnsuportedTLVPacketException() - : senf::Exception("length of length can be max. 4 bytes. Sorry."){} }; - - /** \brief xxx - \todo document me - */ + struct TLVLengthException : public senf::Exception + { + TLVLengthException() + : senf::Exception("TLVLengthException") {} + }; + + class DynamicTLVLengthParser : public detail::packet::IntParserOps, public PacketParserBase @@ -67,60 +61,141 @@ namespace senf { size_type bytes() const; void init() const; - private: - typedef FlagParser < 0 > ExtendedLengthFlagParser; - typedef UIntFieldParser < 1, 8 > FixedLengthParser; - - ExtendedLengthFlagParser extended_length_flag() const { - return parse( 0 ); - } +# include SENF_PARSER() + SENF_PARSER_PRIVATE_BITFIELD ( extended_length_flag, 1, bool ); + SENF_PARSER_PRIVATE_BITFIELD ( fixed_length_field, 7, unsigned ); - FixedLengthParser fixed_length_field() const { - return parse( 0 ); - } - + void shrink(); + void maxValue(DynamicTLVLengthParser::value_type v); + private: void resize(size_type size); }; - /** \brief parse TLVPacket Packet - - \todo document me + + /** \brief Base class for TLV-Packet-Parsers - \see TLVPacketType + BaseTLVPacketParser is the abstract base class for TLV-Packet-Parsers. It defines the + \ref type() field as an \ref senf::UInt8Parser and the \ref length() field as a + DynamicTLVLengthParser. The length field is read-only. + + To create your own \c TLVParser you have to inherit from BaseTLVPacketParser (don't + forget \ref SENF_PARSER_INHERIT) and define the \c value field. In the following example + the value is a vector of MacAddresses: + \code + struct MacAddressesTLVParser : public BaseTLVPacketParser { + # include SENF_PARSER() + SENF_PARSER_INHERIT ( BaseTLVPacketParser ); + SENF_PARSER_VECTOR ( value, bytes(length), senf::MACAddressParser ); + SENF_PARSER_FINALIZE( MacAddressesTLVParser ); + }; + + struct MacAddressesTLVPacketType : public PacketTypeBase { + typedef MacAddressesTLVParser parser; + ... + static void finalize(ConcretePacket p) { + p->shrinkLength(); + } + }; + \endcode + + You have to adjust the maximum length value with the \ref maxLengthValue function + before the length value is set. The default maximum value is 127. So, in the above + example adding more than 21 MACAddresses to the vector will throw a TLVLengthException + if you don't call \c macAddressesTLVPacket->maxLengthValue( \e some_value) before. + + \see DynamicTLVLengthParser \n + GenericTLVPacketParser \n */ - template - struct TLVPacketParser : public PacketParserBase + class BaseTLVPacketParser : public PacketParserBase { + public: # include SENF_PARSER() + SENF_PARSER_FIELD ( type, UInt8Parser ); + SENF_PARSER_FIELD_RO ( length, DynamicTLVLengthParser ); + SENF_PARSER_FINALIZE ( BaseTLVPacketParser ); - SENF_PARSER_FIELD( type, TypeParser ); - SENF_PARSER_FIELD( length, LengthParser ); + /** \brief set maximum value of length field + + The size of the length field will be increased if necessary. + \param v maximum value of length field + */ + void maxLengthValue(DynamicTLVLengthParser::value_type v) const { + length_().maxValue(v); + } - SENF_PARSER_FINALIZE(TLVPacketParser); - }; + /** \brief shrink size of length field to minimum - /** \brief generic TLV Packet type + The size of the length field will be decreased to minimum necessary to hold + the current length value. + */ + void shrinkLength() { + length_().shrink(); + }; + + protected: + /// return size of length field + size_type length_bytes() const { return length_().bytes(); }; + /// set length field to given value + void length(DynamicTLVLengthParser::value_type &v) { length_() = v; }; + /// resize the Packet after the length field to given size + senf::safe_data_iterator resizeValue(DynamicTLVLengthParser::value_type size); + }; + + + /** \brief Parser for a generic TLV packet + + \see GenericTLVPacketType + */ + struct GenericTLVPacketParser : public BaseTLVPacketParser + { +# include SENF_PARSER() + SENF_PARSER_INHERIT ( BaseTLVPacketParser ); + SENF_PARSER_SKIP ( length(), 0 ); + SENF_PARSER_FINALIZE ( GenericTLVPacketParser ); + + SENF_PARSER_INIT() { + maxLengthValue( DynamicTLVLengthParser::max_value); + } - \todo document me + senf::PacketInterpreterBase::range value() const; - \ingroup protocolbundle_mpegdvb + template + void value(ForwardReadableRange const &range); + }; + + /** \brief Generic TLV packet + + \par Packet type (typedef): + \ref GenericTLVPacket + + \image html TLV.png + + \ingroup protocolbundle_80221 */ - template - struct TLVPacketType - : public PacketTypeBase + struct GenericTLVPacketType + : public PacketTypeBase, + public PacketTypeMixin { - typedef ConcretePacket > packet; - typedef TLVPacketParser parser; +#ifndef DOXYGEN + typedef PacketTypeMixin mixin; +#endif + typedef ConcretePacket packet; ///< GenericTLV packet typedef + typedef GenericTLVPacketParser parser; ///< typedef to the parser of GenericTLV packet - static optional_range nextPacketRange(packet p); - static size_type initSize(); + using mixin::nextPacketRange; + using mixin::init; + using mixin::initSize; - static void finalize(packet p); + /** \brief Dump given GenericTLVPacket in readable form to given output stream */ + static void dump(packet p, std::ostream & os); + static void finalize(packet p); ///< Finalize packet. + /**< shrink size of length field to minimum + \see BaseTLVPacketParser::shrinkLength() */ - static void dump(packet p, std::ostream & os); }; - typedef ConcretePacket > MIHInfoElement; + /** \brief GenericTLV packet typedef */ + typedef ConcretePacket GenericTLVPacket; }