///////////////////////////////cc.p////////////////////////////////////////
using namespace senf;
-BOOST_AUTO_UNIT_TEST(MIHPacket_MIHFId)
-{
- MIHFId id ( MACAddress::from_string("01:02:03:04:05:06"));
- BOOST_CHECK_EQUAL( id.type(), MIHFId::MACAddress);
- BOOST_CHECK_EQUAL( id, MIHFId( MACAddress::from_string("01:02:03:04:05:06")));
- BOOST_CHECK( id != MIHFId( MACAddress::from_string("01:02:03:04:05:07")));
- BOOST_CHECK( id != MIHFId( INet4Address::from_string("128.129.130.131")));
- BOOST_CHECK( id < MIHFId( MACAddress::from_string("01:02:03:04:05:07")));
- BOOST_CHECK( id < MIHFId( INet4Address::from_string("128.129.130.131")));
-}
-
BOOST_AUTO_UNIT_TEST(MIHPacket_msgId)
{
MIHPacket mihPacket (MIHPacket::create());
mihPacket->src_mihfId().value( "senf@berlios.de");
mihPacket->dst_mihfId().value( "test");
mihPacket.finalizeThis();
-
+
unsigned char data[] = {
// MIH header
- 0x10, 0x54, 0x00, 0x00, 0x00, 0x15, 0x00, 0x17,
+ 0x10, 0x54, 0x00, 0x00, 0x00, 0x15, 0x00, 0x19,
// source MIHF_ID TLV:
- 0x01, 0x0f, // type, length
+ 0x01, 0x10, // type, length
+ 0x0f, // value-length
0x73, 0x65, 0x6e, 0x66, 0x40, 0x62, 0x65, 0x72, 0x6c,
0x69, 0x6f, 0x73, 0x2e, 0x64, 0x65, // value
// destination MIHF_ID TLV:
- 0x02, 0x04, 0x74, 0x65, 0x73, 0x74
+ 0x02, 0x05, 0x04, 0x74, 0x65, 0x73, 0x74
};
- BOOST_CHECK(equal( mihPacket.data().begin(), mihPacket.data().end(), data ));
+ SENF_CHECK_EQUAL_COLLECTIONS( data, data+sizeof(data),
+ mihPacket.data().begin(), mihPacket.data().end() );
BOOST_CHECK_EQUAL( mihPacket->src_mihfId().valueAsString(), "senf@berlios.de");
BOOST_CHECK_EQUAL( mihPacket->dst_mihfId().valueAsString(), "test");
// the maximum length of a MIHF_ID is 253 octets
BOOST_CHECK_THROW( mihPacket->dst_mihfId().value( std::string(254, 'x')), std::length_error);
-
// now expand a MIHF_ID
- mihPacket->dst_mihfId().maxLengthValue(253);
- mihPacket->dst_mihfId().value( std::string(200, 'x'));
+ // first the tricky one: when setting the maximum id length to 128 the TLV length field
+ // is set to 129 and therefore expanded to 2 bytes; the id-length field is still 1 byte long
+ mihPacket->dst_mihfId().maxIdLength(128);
+ mihPacket->dst_mihfId().value( std::string(128, 'x'));
mihPacket.finalizeThis();
-
- BOOST_CHECK_EQUAL( mihPacket.size(), unsigned(8 + 17 + 203));
- BOOST_CHECK_EQUAL( mihPacket->payloadLength(), 17 + 203);
- BOOST_CHECK_EQUAL( mihPacket->dst_mihfId().length(), 200u);
- BOOST_CHECK_EQUAL( senf::bytes(mihPacket->dst_mihfId()), 203u);
-
+ // packet size is now MIH header (8 bytes) + src MIHIFId TLV (18 bytes) +
+ // dst MIHIFId TLV (1 byte type + 2 byte TLV length + 1 byte id length + 128 id value)
+ BOOST_CHECK_EQUAL( mihPacket.size(), unsigned(8 + 18 + 1+2+1+128));
+ BOOST_CHECK_EQUAL( mihPacket->payloadLength(), 18 + 1+2+1+128);
+ BOOST_CHECK_EQUAL( mihPacket->dst_mihfId().length(), 1+128);
+ BOOST_CHECK_EQUAL( senf::bytes(mihPacket->dst_mihfId()), 1+2+1+128);
+ // now we extend the dst id to 129 bytes; than we have 2 bytes tlv length and 2 bytes
+ // id-length field
+ mihPacket->dst_mihfId().maxIdLength(129);
+ mihPacket->dst_mihfId().value( std::string(129, 'x'));
+ mihPacket.finalizeThis();
+ // packet size is now MIH header (8 bytes) + src MIHIFId TLV (18 bytes) +
+ // dst MIHIFId TLV (1 byte type + 2 byte TLV length + 2 byte id length + 128 id value)
+ BOOST_CHECK_EQUAL( mihPacket.size(), unsigned(8 + 18 + 1+2+2+129));
+ BOOST_CHECK_EQUAL( mihPacket->payloadLength(), 18 + 1+2+2+129);
+ BOOST_CHECK_EQUAL( mihPacket->dst_mihfId().length(), 2+129);
+ BOOST_CHECK_EQUAL( senf::bytes(mihPacket->dst_mihfId()), 1+2+2+129);
+ // finally we shrink to dst id field
+ mihPacket->dst_mihfId().value( "test");
+ mihPacket.finalizeThis();
+ SENF_CHECK_EQUAL_COLLECTIONS( data, data+sizeof(data),
+ mihPacket.data().begin(), mihPacket.data().end() );
+
std::ostringstream oss (std::ostringstream::out);
SENF_CHECK_NO_THROW( mihPacket.dump( oss));
}
unsigned char data[] = {
// MIH header
- 0x10, 0x54, 0x00, 0x00, 0x00, 0x15, 0x00, 0x1c,
+ 0x10, 0x54, 0x00, 0x00, 0x00, 0x15, 0x00, 0x1e,
// source MIHF_ID TLV:
- 0x01, 0x0c, // type, length
+ 0x01, 0x0d, // type, length
+ 0x0c, // value-length
0x5c, 0x01, 0x5c, 0x02, 0x5c, 0x03, 0x5c, 0x04, 0x5c, 0x05, 0x5c, 0x06, // value (nai-encoded)
// destination MIHF_ID TLV:
- 0x02, 0x0c, // type, length
+ 0x02, 0x0d, // type, length
+ 0x0c, // value-length
0x5c, 0x07, 0x5c, 0x08, 0x5c, 0x09, 0x5c, 0x0a, 0x5c, 0x0b, 0x5c, 0x0c // value (nai-encoded)
};
SENF_CHECK_EQUAL_COLLECTIONS( data, data+sizeof(data),
unsigned char data[] = {
// MIH header
- 0x10, 0x54, 0x00, 0x00, 0x00, 0x15, 0x00, 0x14,
+ 0x10, 0x54, 0x00, 0x00, 0x00, 0x15, 0x00, 0x16,
// source MIHF_ID TLV:
- 0x01, 0x08, // type, length
+ 0x01, 0x09, // type, length
+ 0x08, // value-length
0x5c, 0x80, 0x5c, 0x81, 0x5c, 0x82, 0x5c, 0x83, // value (nai-encoded)
// destination MIHF_ID TLV:
- 0x02, 0x08, // type, length
+ 0x02, 0x09, // type, length
+ 0x08, // value-length
0x5c, 0x84, 0x5c, 0x85, 0x5c, 0x86, 0x5c, 0x87 // value (nai-encoded)
};
SENF_CHECK_EQUAL_COLLECTIONS( data, data+sizeof(data),
unsigned char data[] = {
// MIH header
- 0x10, 0x54, 0x00, 0x00, 0x00, 0x15, 0x00, 0x44,
+ 0x10, 0x54, 0x00, 0x00, 0x00, 0x15, 0x00, 0x46,
// source MIHF_ID TLV:
- 0x01, 0x20, // type, length
+ 0x01, 0x21, // type, length
+ 0x20, // value-length
// value (nai-encoded):
0x5c, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x5c, 0x00,
0x5c, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x5c, 0x00,
0x5c, 0x00, 0x5c, 0x00, 0x5c, 0xff, 0x5c, 0xff,
0x5c, 0x01, 0x5c, 0x02, 0x5c, 0x03, 0x5c, 0x04,
// destination MIHF_ID TLV:
- 0x02, 0x20, // type, length
+ 0x02, 0x21, // type, length
+ 0x20, // value-length
// value (nai-encoded):
0x5c, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x5c, 0x00,
0x5c, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x5c, 0x00,
// variable payload length:
0x00, 0x29,
// source MIHF_ID TLV:
- 0x01, 0x0f, // type, length
+ 0x01, 0x10, // type, length
+ 0x0f, // value-length
0x73, 0x65, 0x6e, 0x66, 0x40, 0x62, 0x65, 0x72, 0x6c,
- 0x69, 0x6f, 0x73, 0x2e, 0x64, 0x65, // value ("senf@berlios.de")
+ 0x69, 0x6f, 0x73, 0x2e, 0x64, 0x65, // value
// destination MIHF_ID TLV:
- 0x02, 0x04, 0x74, 0x65, 0x73, 0x74, // type, length, value ("test")
+ 0x02, 0x05, 0x04, 0x74, 0x65, 0x73, 0x74,
// MIH Payload (two test tlvs)
// first test tlv
0x42, // type
// MIH header
0x10, 0x54, 0x00, 0x00, 0x00, 0x15,
// variable payload length:
- 0x00, 0x29,
+ 0x00, 0x2b,
// source MIHF_ID TLV:
- 0x01, 0x0f, // type, length
+ 0x01, 0x10, // type, length
+ 0x0f, // value-length
0x73, 0x65, 0x6e, 0x66, 0x40, 0x62, 0x65, 0x72, 0x6c,
- 0x69, 0x6f, 0x73, 0x2e, 0x64, 0x65, // value ("senf@berlios.de")
+ 0x69, 0x6f, 0x73, 0x2e, 0x64, 0x65, // value
// destination MIHF_ID TLV:
- 0x02, 0x04, 0x74, 0x65, 0x73, 0x74, // type, length, value ("test")
+ 0x02, 0x05, 0x04, 0x74, 0x65, 0x73, 0x74,
// MIH Payload (two test tlvs)
// first test tlv
0x42, // type
hexdump(src_mihfId.begin(), src_mihfId.end(), os);
}
+prefix_ void senf::MIHFIdTLVParser::finalize()
+{
+ protect(), idLength_().finalize();
+ length_() << idLength() + idLength_().bytes();
+ MIHBaseTLVParser::finalize();
+}
+
+prefix_ void senf::MIHFIdTLVParser::maxIdLength(boost::uint8_t maxLength)
+{
+ // the maximum length of a MIHF_ID is 253 octets (see F.3.11 in 802.21)
+ if (maxLength > 253)
+ throw std::length_error("maximum length of a MIHF_ID is 253 octets");
+ protect(), idLength_().maxValue( maxLength);
+ maxLengthValue( maxLength + senf::bytes(idLength_()));
+}
+
+prefix_ senf::safe_data_iterator senf::MIHFIdTLVParser::resizeValueField(
+ MIHTLVLengthParser::value_type size)
+{
+ MIHTLVLengthParser::value_type current_length ( idLength());
+ idLength_() << size;
+ length_() << size + idLength_().bytes();
+
+ safe_data_iterator si (data(), valueBegin());
+ if (current_length > size)
+ data().erase( si, boost::next(si, current_length-size));
+ else
+ data().insert( si, size-current_length, 0);
+ return si;
+}
+
prefix_ void senf::MIHFIdTLVParser::value(std::string const & id)
{
size_type str_size (id.size());
prefix_ void senf::MIHFIdTLVParser::value(senf::MACAddress const & addr)
{
- safe_data_iterator si = resizeValueField(12);
+ safe_data_iterator si = resizeValueField(6*2);
std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si));
}
prefix_ void senf::MIHFIdTLVParser::value(senf::INet4Address const & addr)
{
- safe_data_iterator si = resizeValueField(8);
+ safe_data_iterator si = resizeValueField(4*2);
std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si));
}
prefix_ void senf::MIHFIdTLVParser::value(senf::INet6Address const & addr)
{
- safe_data_iterator si = resizeValueField(32);
+ safe_data_iterator si = resizeValueField(16*2);
std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si));
}
prefix_ void senf::MIHFIdTLVParser::value(senf::EUI64 const & addr)
{
- safe_data_iterator si = resizeValueField(16);
+ safe_data_iterator si = resizeValueField(8*2);
std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si));
}
<< ( value()==0 ? " (infinite)" : " seconds") << std::endl;
}
-
-///////////////////////////////////////////////////////////////////////////
-// senf::MIHBaseTLVParser
-
-prefix_ senf::safe_data_iterator senf::MIHBaseTLVParser::resizeValueField(
- MIHTLVLengthParser::value_type size)
-{
- MIHTLVLengthParser::value_type current_length ( length());
- length_() << size;
-
- safe_data_iterator si (data(), boost::next(i(), 1 + length_().bytes() ));
- if (current_length > size)
- data().erase( si, boost::next(si, current_length-size));
- else
- data().insert( si, size-current_length, 0);
- return si;
-}
-
-
///////////////////////////////////////////////////////////////////////////
// senf::MIHTLVLengthParser
if (b != 5) resize_(5);
}
-prefix_ void senf::MIHTLVLengthParser:: maxValue(MIHTLVLengthParser::value_type v)
+prefix_ void senf::MIHTLVLengthParser::maxValue(MIHTLVLengthParser::value_type v)
{
if (v <= 128)
return;
///////////////////////////////////////////////////////////////////////////
// MIHFIdTLVParser
+prefix_ senf::PacketParserBase::data_iterator senf::MIHFIdTLVParser::valueBegin()
+ const
+{
+ return i( idValue_offset());
+}
+
+prefix_ senf::PacketParserBase::data_iterator senf::MIHFIdTLVParser::valueEnd()
+ const
+{
+ return i( idValue_offset() + idLength());
+}
+
prefix_ std::string senf::MIHFIdTLVParser::valueAsString()
const
{
- return std::string( i(1+length_().bytes()), i(1+length_().bytes()+length()) );
+ return std::string( valueBegin(), valueEnd());
}
prefix_ senf::MACAddress senf::MIHFIdTLVParser::valueAsMACAddress()
const
{
- return MACAddress::from_data(
- getNAIDecodedIterator( i(1+length_().bytes()), i(1+length_().bytes()+12) ));
+ if (idLength() != 6*2) throw WrapException<std::bad_cast>(std::bad_cast())
+ << "length of MIHF_ID does not match for a MAC address";
+ return MACAddress::from_data( getNAIDecodedIterator( valueBegin(), valueEnd()));
}
prefix_ senf::INet4Address senf::MIHFIdTLVParser::valueAsINet4Address()
const
{
- return INet4Address::from_data(
- getNAIDecodedIterator( i(1+length_().bytes()), i(1+length_().bytes()+8) ));
+ if (idLength() != 4*2) throw WrapException<std::bad_cast>(std::bad_cast())
+ << "length of MIHF_ID does not match for a INet4 address";
+ return INet4Address::from_data( getNAIDecodedIterator( valueBegin(), valueEnd()));
}
prefix_ senf::INet6Address senf::MIHFIdTLVParser::valueAsINet6Address()
const
{
- return INet6Address::from_data(
- getNAIDecodedIterator( i(1+length_().bytes()), i(1+length_().bytes()+32) ));
+ if (idLength() != 16*2) throw WrapException<std::bad_cast>(std::bad_cast())
+ << "length of MIHF_ID does not match for a INet6 address";
+ return INet6Address::from_data( getNAIDecodedIterator( valueBegin(), valueEnd()));
}
prefix_ senf::EUI64 senf::MIHFIdTLVParser::valueAsEUI64()
const
{
- return EUI64::from_data(
- getNAIDecodedIterator( i(1+length_().bytes()), i(1+length_().bytes()+16) ));
+ if (idLength() != 8*2) throw WrapException<std::bad_cast>(std::bad_cast())
+ << "length of MIHF_ID does not match for a EUI64 address";
+ return EUI64::from_data( getNAIDecodedIterator( valueBegin(), valueEnd()));
}
prefix_ bool senf::MIHFIdTLVParser::valueEquals( std::string const &id)
prefix_ bool senf::MIHFIdTLVParser::valueEquals( senf::MACAddress const & addr)
const
{
- return length()==12 && addr==valueAsMACAddress();
+ return idLength()==12 && addr==valueAsMACAddress();
}
prefix_ bool senf::MIHFIdTLVParser::valueEquals( senf::INet4Address const & addr)
const
{
- return length()==8 && addr==valueAsINet4Address();
+ return idLength()==8 && addr==valueAsINet4Address();
}
prefix_ bool senf::MIHFIdTLVParser::valueEquals( senf::INet6Address const & addr)
const
{
- return length()==32 && addr==valueAsINet6Address();
+ return idLength()==32 && addr==valueAsINet6Address();
}
prefix_ bool senf::MIHFIdTLVParser::valueEquals( senf::EUI64 const & addr)
const
{
- return length()==16 && addr==valueAsEUI64();
+ return idLength()==16 && addr==valueAsEUI64();
}
prefix_ bool senf::MIHFIdTLVParser::valueEquals( MIHFId const & id)
\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
+ before the length value is set. The default maximum value is 128. 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.
+ if you don't call \c maxLengthValue( \e some_value) before.
\see MIHTLVLengthParser \n
MIHGenericTLVParser \n
The size of the length field will be decreased to minimum necessary to hold
the current length value.
*/
- void finalizeLength() {
+ void finalize() {
protect(), length_().finalize();
};
typedef GenericTLVParserRegistry<MIHBaseTLVParser> Registry;
-
- protected:
- /// resize the packet after the length field to given size
- senf::safe_data_iterator resizeValueField(MIHTLVLengthParser::value_type size);
};
+
/** \brief Parser for a generic TLV packet
*/
/** \brief Parse a MIHF_ID
- the maximum length of a MIHF_ID is 253 octets (see F.3.11 in 802.21)
- we could set maxLengthValue in init(), but for the most MIHF_IDs the default
- maximum length of 127 should be enough.
+ Note that the maximum length of a MIHF_ID is 253 octets (see F.3.11 in 802.21)
+ We could set maxLengthValue in init(), but for the most MIHF_IDs the default
+ maximum length of 128 should be enough.
- \note you must call mihfIdPacket.maxLengthValue( 253) *before*
- setting longer MIHF_IDs values.
+ \note you must call maxIdLength( 253) *before* setting MIHF_IDs values longer
+ than 128.
+
+ \see MIHFId
*/
class MIHFIdTLVParser : public MIHBaseTLVParser
{
# include SENF_PARSER()
SENF_PARSER_INHERIT ( MIHBaseTLVParser );
- SENF_PARSER_SKIP ( length(), 0 );
+ SENF_PARSER_FIELD_RO ( idLength, MIHTLVLengthParser );
+ SENF_PARSER_LABEL ( idValue );
+ SENF_PARSER_SKIP ( idLength(), 0 );
SENF_PARSER_FINALIZE ( MIHFIdTLVParser );
public:
- ///\name value setters
+ ///\name Value setters
///@{
void value( MIHFId const & id);
void value( senf::EUI64 const & addr);
///@}
- ///\name value getters
+ ///\name Value getters
///@{
MIHFId valueAs( MIHFId::Type type) const;
senf::EUI64 valueAsEUI64() const;
///@}
- ///\name value comparisons
+ ///\name Value comparisons
///@{
bool valueEquals( MIHFId const & id) const;
///@}
void dump(std::ostream & os) const;
+ void maxIdLength(boost::uint8_t maxLength);
+ void finalize();
private:
+ /// resize the packet after the length field to given size
+ senf::safe_data_iterator resizeValueField(MIHTLVLengthParser::value_type size);
+
+ data_iterator valueBegin() const;
+ data_iterator valueEnd() const;
+
template <class OutputIterator>
struct binaryNAIEncoder {
binaryNAIEncoder(OutputIterator & i);
};
};
+ /** \brief Parser for 802.21 source MIHF_ID TLV
+ */
struct MIHFSrcIdTLVParser : public MIHFIdTLVParser
{
MIHFSrcIdTLVParser(data_iterator i, state_type s) : MIHFIdTLVParser(i,s) {}
void dump(std::ostream & os) const;
};
+ /** \brief Parser for 802.21 destination MIHF_ID TLV
+ */
struct MIHFDstIdTLVParser : public MIHFIdTLVParser
{
MIHFDstIdTLVParser(data_iterator i, state_type s) : MIHFIdTLVParser(i,s) {}