Skip to content
Snippets Groups Projects
DtcpPacket.hh 5.33 KiB
Newer Older
dw6's avatar
dw6 committed
// Copyright (C) 2007 
// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
// Kompetenzzentrum NETwork research (NET)
//     David Wagner <david.wagner@fokus.fraunhofer.de>
//
#ifndef DTCPPACKET_HH_
#define DTCPPACKET_HH_

#include "../../Packets/Packets.hh"
#include "../../Packets/DefaultBundle/IpV4Packet.hh"
#include "../../Packets/DefaultBundle/IpV6Packet.hh"

namespace senf {
    
    //first we have to define some helpers
    struct DTCPIpV4AddressListParser : public PacketParserBase {
#       include SENF_PARSER()        
        SENF_PARSER_PRIVATE_FIELD ( num_of_fbips, Parse_UInt8 );
        SENF_PARSER_PRIVATE_FIELD ( reserved ,    Parse_UInt8 );   //must be zero 
        SENF_PARSER_VEC_N         ( fbiplist,     num_of_fbips, Parse_INet4Address );

	SENF_PARSER_FINALIZE(DTCPIpV4AddressListParser);
    };
        
    struct DTCPIpV6AddressListParser : public PacketParserBase {
#       include SENF_PARSER()        
        SENF_PARSER_PRIVATE_FIELD ( num_of_fbips, Parse_UInt8 );
        SENF_PARSER_PRIVATE_FIELD ( reserved,     Parse_UInt8 );   //must be zero 
        SENF_PARSER_VEC_N         ( fbiplist,     num_of_fbips, Parse_INet6Address );

	SENF_PARSER_FINALIZE(DTCPIpV6AddressListParser);
    };

    /** \brief Parse a DTCP packet

        Parser implementing the DTCP packet according to RFC 3077
        
        \see DTCPPacketType
     */
    struct Parse_DTCPPacket : public PacketParserBase
    {
#       include SENF_PARSER()

        SENF_PARSER_BITFIELD         ( version_number,       4, unsigned );  // =1 according to rfc3077
        SENF_PARSER_BITFIELD         ( command,              4, unsigned );  // 1=JOIN 2=LEAVE
        SENF_PARSER_FIELD            ( interval,             Parse_UInt8 );  // 5 according to rfc3077
        SENF_PARSER_FIELD            ( sequence_number,      Parse_UInt16 );
        SENF_PARSER_PRIVATE_BITFIELD ( reserved,             3, unsigned );
        SENF_PARSER_BITFIELD         ( receive_capable_feed, 1, bool );      // 0=send only, 1=receive_capable_feed
        SENF_PARSER_BITFIELD         ( ip_version,           4, unsigned );  // 4=IPv4, 6=IPv6
        SENF_PARSER_FIELD            ( tunnel_protocol,      Parse_UInt8 ); 
		/* Please consider the following comments on the implementation given in this class: 
		 * 1. you could think of simply using SENF_PARSER_PRIVATE_VARIANT and List / Vectorparser like this:
		 * SENF_PARSER_PRIVATE_VARIANT  ( fbiplist,             ip_version,
         *                                                       (senf::VoidPacketParser) //ip_version=0
         *                                                       (senf::VoidPacketParser) //1
         *                                                       (senf::VoidPacketParser) //2
         *                                                       (senf::VoidPacketParser) //3
         *                                                       (senf::Parse_ListB< IpV4Packet, num_of_fbips>) //4 
         *                                                       (senf::VoidPacketParser) //5
         *                                                       (senf::Parse_ListB< IpV6Packet, num_of_fbips>) ); //6
         * This can't work for two reasons: 
         * 		-SENF_PARSER_PRIVATE_VARIANT only accepts 6 templates in types but you have to start from 0.
         * 		-you NEVER can use templated Parsers in these macros since the macro-preprocessor won't recognize the <> brackets and will
         * 			interpret the ","
         * 
         * The first problem is solved by using (actually inventing)  SENF_PARSER_VARIANT_TRANS which has the same limitations 
         * 		concerning the number of types but isn't limited to the values used. This is achieved by a translating function 
         * 		as you can see. 
         * The second problem is solved by introducing Helper-Parser which cover both the list and the number field. By that no 
         * 		templates have to be used. 
		*/

		struct ip_version_translator {
		    static unsigned fromChooser(ip_version_t::value_type in) {
			switch (in) { 
			case 4: return 0;
			case 6: return 1;
			}
		    }
		    static ip_version_t::value_type toChooser(unsigned in) {
			switch (in) {
			    case 0: return 4;
			    case 1: return 6; 
			}
		    }
		};
    
        SENF_PARSER_VARIANT_TRANS    ( fbiplist,             ip_version, ip_version_translator,
                                                                 (senf::DTCPIpV4AddressListParser)        //IPv4 
                                                                 (senf::DTCPIpV6AddressListParser) );     //IPv6

	SENF_PARSER_FINALIZE(Parse_DTCPPacket);
    };
    
    /** \brief DTCP packet
        
        \par Packet type (typedef):
            \ref DTCPPacket

        \par Fields:
            \ref Parse_DTCPPacket

        \ingroup protocolbundle_mpegdvb
     */
    struct DTCPPacketType
        : public PacketTypeBase,
          public PacketTypeMixin<DTCPPacketType>
    {
        typedef PacketTypeMixin<DTCPPacketType> mixin;
        typedef ConcretePacket<DTCPPacketType> packet;
        typedef Parse_DTCPPacket parser;
    
        using mixin::nextPacketRange;
        using mixin::init;
        using mixin::initSize;
        
        static void dump(packet p, std::ostream & os);
    };
    
    /** \brief DTCP packet typedef */
    typedef DTCPPacketType::packet DTCPPacket;
}

#endif /*DTCPPACKET_HH_*/