// Custom includes
#include "../../Packets/Packets.hh"
+#include "../../Utils/hexdump.hh"
#include <boost/io/ios_state.hpp>
#define prefix_
+prefix_ std::string senf::MIHFId_TLVParser::asString()
+ const
+{
+ return std::string( i(1+length_bytes()), i(1+length_bytes()+length()) );
+}
+
+prefix_ void senf::MIHFId_TLVParser::setString(std::string const &id)
+{
+ size_type str_size (id.size());
+ // the maximum length of a MIHF_ID is 253 octets (see F.3.11 in 802.21)
+ if (str_size > 253)
+ throw std::length_error("maximum length of a MIHF_ID is 253 octets");
+ safe_data_iterator si = resizeValue( str_size);
+ std::copy( id.begin(), id.end(), si);
+}
+
+
+prefix_ senf::MACAddress senf::MIHFId_TLVParser::asMACAddress()
+ const
+{
+ return MACAddress::from_data(
+ getNAIDecodedIterator( i(1+length_bytes()), i(1+length_bytes()+12) ));
+}
+
+prefix_ void senf::MIHFId_TLVParser::setMACAddress(senf::MACAddress const &mac)
+{
+ safe_data_iterator si = resizeValue(12);
+ std::copy( mac.begin(), mac.end(), getNAIEncodedOutputIterator(si));
+}
+
+
+prefix_ senf::INet4Address senf::MIHFId_TLVParser::asINet4Address()
+ const
+{
+ return INet4Address::from_data(
+ getNAIDecodedIterator( i(1+length_bytes()), i(1+length_bytes()+8) ));
+}
+
+prefix_ void senf::MIHFId_TLVParser::setINet4Address(senf::INet4Address const &addr)
+{
+ safe_data_iterator si = resizeValue(8);
+ std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si));
+}
+
+prefix_ senf::INet6Address senf::MIHFId_TLVParser::asINet6Address()
+ const
+{
+ return INet6Address::from_data(
+ getNAIDecodedIterator( i(1+length_bytes()), i(1+length_bytes()+32) ));
+}
+
+prefix_ void senf::MIHFId_TLVParser::setINet6Address(senf::INet6Address const &addr)
+{
+ safe_data_iterator si = resizeValue(32);
+ std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si));
+}
+
+
prefix_ void senf::MIHPacketType::dump(packet p, std::ostream &os)
{
boost::io::ios_all_saver ias(os);
<< " Opcode: " << unsigned( p->opcode()) << "\n"
<< " AID: " << unsigned( p->aid()) << "\n"
<< " Transaction ID: " << unsigned( p->transactionId()) << "\n"
- << " payload length: " << unsigned( p->payloadLength()) << "\n";
+ << " payload length: " << unsigned( p->payloadLength()) << "\n"
+ << " source MIHF_Id TLV:\n"
+ << " length: " << unsigned (p->src_mihfId().length()) << "\n"
+ << " value:\n";
+ std::string src_mihfId (p->src_mihfId().asString());
+ hexdump(src_mihfId.begin(), src_mihfId.end(), os);
+ os << " destination MIHF_Id TLV:\n"
+ << " length: " << unsigned (p->dst_mihfId().length()) << "\n"
+ << " value:\n";
+ std::string dst_mihfId (p->dst_mihfId().asString());
+ hexdump(dst_mihfId.begin(), dst_mihfId.end(), os);
}
prefix_ void senf::MIHPacketType::finalize(packet p)
{
- p->source_length() << senf::bytes( p->source_mihf_id());
- p->destination_length() << senf::bytes( p->destination_mihf_id());
+ p->src_mihfId().shrinkLength();
+ p->dst_mihfId().shrinkLength();
p->payloadLength_() << p.size() - 8;
}
// Custom includes
#include "../../Packets/Packets.hh"
+#include "../../Socket/Protocols/Raw/MACAddress.hh"
+#include "../../Socket/Protocols/INet/INet4Address.hh"
+#include "../../Socket/Protocols/INet/INet6Address.hh"
#include "TLVPacket.hh"
+#include <boost/function_output_iterator.hpp>
+#include <boost/iterator/filter_iterator.hpp>
+
//#include "MIHPacket.mpp"
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
- struct MIHF_IdParser : public PacketParserBase
+ // 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.
+ // The user must call mihPacket->src_mihfId().maxLengthValue( 127) before
+ // setting longer MIHF_IDs
+ class MIHFId_TLVParser : public BaseTLVPacketParser
{
# include SENF_PARSER()
+ SENF_PARSER_INHERIT ( BaseTLVPacketParser );
+ SENF_PARSER_SKIP ( length(), 0 );
+ SENF_PARSER_FINALIZE ( MIHFId_TLVParser );
- SENF_PARSER_FINALIZE ( MIHF_IdParser );
+ std::string asString() const;
+ void setString(std::string const &id);
+
+ senf::MACAddress asMACAddress() const;
+ void setMACAddress(senf::MACAddress const &mac);
+
+ senf::INet4Address asINet4Address() const;
+ void setINet4Address(senf::INet4Address const &addr);
+
+ senf::INet6Address asINet6Address() const;
+ void setINet6Address(senf::INet6Address const &addr);
+
+ private:
+ template <class OutputIterator>
+ struct binaryNAIEncoder {
+ binaryNAIEncoder(OutputIterator &i) : i_(i) {}
+ void operator()(const boost::uint8_t &v) const {
+ *i_++ = '\\';
+ *i_++ = v;
+ }
+ OutputIterator &i_;
+ };
+ template <class OutputIterator>
+ static boost::function_output_iterator<binaryNAIEncoder<OutputIterator> > getNAIEncodedOutputIterator(OutputIterator i) {
+ return boost::make_function_output_iterator(binaryNAIEncoder<OutputIterator>(i));
+ }
+
+ struct binaryNAIDecoder {
+ binaryNAIDecoder() : readNextByte_(true) {}
+ bool operator()(const boost::uint8_t &v) {
+ readNextByte_ = readNextByte_ ? false : true;
+ return readNextByte_;
+ }
+ bool readNextByte_;
+ };
+ template <class Iterator>
+ static boost::filter_iterator<binaryNAIDecoder, Iterator> getNAIDecodedIterator(Iterator begin, Iterator end) {
+ return boost::make_filter_iterator<binaryNAIDecoder>(begin, end);
+ }
};
struct MIHPacketParser : public PacketParserBase
SENF_PARSER_FIELD_RO ( payloadLength, UInt16Parser );
// Source MIHF Id
- SENF_PARSER_PRIVATE_FIELD ( source_type, UInt8Parser );
- SENF_PARSER_PRIVATE_FIELD ( source_length, DynamicTLVLengthParser );
- SENF_PARSER_FIELD ( source_mihf_id, MIHF_IdParser );
-
+ SENF_PARSER_FIELD ( src_mihfId, MIHFId_TLVParser );
// Destination MIHF Id
- SENF_PARSER_PRIVATE_FIELD ( destination_type, UInt8Parser );
- SENF_PARSER_PRIVATE_FIELD ( destination_length, DynamicTLVLengthParser );
- SENF_PARSER_FIELD ( destination_mihf_id, MIHF_IdParser );
+ SENF_PARSER_FIELD ( dst_mihfId, MIHFId_TLVParser );
SENF_PARSER_FINALIZE ( MIHPacketParser );
SENF_PARSER_INIT() {
version_() = 1;
- source_type() = 1;
- destination_type() = 2;
+ src_mihfId().type() = 1;
+ dst_mihfId().type() = 2;
}
friend class MIHPacketType;
#include <boost/test/test_tools.hpp>
#include "MIHPacket.hh"
-#include "senf/Utils/hexdump.hh"
+
using namespace senf;
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
-BOOST_AUTO_UNIT_TEST(MIHPacket_create)
+BOOST_AUTO_UNIT_TEST(MIHPacket_create_string)
+{
+ MIHPacket mihPacket (MIHPacket::create());
+ // set some fields
+ mihPacket->fragmentNr() = 42;
+ mihPacket->transactionId() = 21;
+ mihPacket->src_mihfId().setString( "senf@berlios.de");
+ mihPacket->dst_mihfId().setString( "test");
+ mihPacket.finalizeThis();
+
+ unsigned char data[] = {
+ // MIH header
+ 0x10, 0x54, 0x00, 0x00, 0x00, 0x15, 0x00, 0x17,
+ // source MIHF_ID TLV:
+ 0x01, 0x0f, // type, 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
+ };
+ BOOST_CHECK(equal( mihPacket.data().begin(), mihPacket.data().end(), data ));
+ BOOST_CHECK_EQUAL( mihPacket->src_mihfId().asString(), "senf@berlios.de");
+ BOOST_CHECK_EQUAL( mihPacket->dst_mihfId().asString(), "test");
+
+ // now expand a MIHF_ID
+ mihPacket->dst_mihfId().maxLengthValue(253);
+ mihPacket->dst_mihfId().setString( std::string(200, 'x'));
+ mihPacket.finalizeThis();
+
+ BOOST_CHECK_EQUAL( mihPacket.size(), 8 + 17 + 203);
+ BOOST_CHECK_EQUAL( mihPacket->payloadLength(), 17 + 203);
+ BOOST_CHECK_EQUAL( mihPacket->dst_mihfId().length(), 200);
+ BOOST_CHECK_EQUAL( senf::bytes(mihPacket->dst_mihfId()), 203);
+}
+
+
+BOOST_AUTO_UNIT_TEST(MIHPacket_create_mac)
{
MIHPacket mihPacket (MIHPacket::create());
// set some fields
mihPacket->fragmentNr() = 42;
mihPacket->transactionId() = 21;
+ mihPacket->src_mihfId().setMACAddress( MACAddress::from_string("01:02:03:04:05:06"));
+ mihPacket->dst_mihfId().setMACAddress( MACAddress::from_string("07:08:09:0a:0b:0c"));
mihPacket.finalizeThis();
-// mihPacket.dump(std::cout);
-// senf::hexdump(mihPacket.data().begin(), mihPacket.data().end(), std::cout);
+ unsigned char data[] = {
+ // MIH header
+ 0x10, 0x54, 0x00, 0x00, 0x00, 0x15, 0x00, 0x1c,
+ // source MIHF_ID TLV:
+ 0x01, 0x0c, // type, length
+ 0x5c, 0x01, 0x5c, 0x02, 0x5c, 0x03, 0x5c, 0x04, 0x5c, 0x05, 0x5c, 0x06, // value (nai-encoded)
+ // destination MIHF_ID TLV:
+ 0x02, 0x0c, // type, length
+ 0x5c, 0x07, 0x5c, 0x08, 0x5c, 0x09, 0x5c, 0x0a, 0x5c, 0x0b, 0x5c, 0x0c // value (nai-encoded)
+ };
+ BOOST_CHECK(equal( mihPacket.data().begin(), mihPacket.data().end(), data ));
+ BOOST_CHECK_EQUAL(
+ mihPacket->src_mihfId().asMACAddress(),
+ MACAddress::from_string("01:02:03:04:05:06"));
+ BOOST_CHECK_EQUAL(
+ mihPacket->dst_mihfId().asMACAddress(),
+ MACAddress::from_string("07:08:09:0a:0b:0c"));
+}
+
+
+BOOST_AUTO_UNIT_TEST(MIHPacket_create_inet4)
+{
+ MIHPacket mihPacket (MIHPacket::create());
+ // set some fields
+ mihPacket->fragmentNr() = 42;
+ mihPacket->transactionId() = 21;
+ mihPacket->src_mihfId().setINet4Address( INet4Address::from_string("128.129.130.131"));
+ mihPacket->dst_mihfId().setINet4Address( INet4Address::from_string("132.133.134.135"));
+ mihPacket.finalizeThis();
+
+ unsigned char data[] = {
+ // MIH header
+ 0x10, 0x54, 0x00, 0x00, 0x00, 0x15, 0x00, 0x14,
+ // source MIHF_ID TLV:
+ 0x01, 0x08, // type, length
+ 0x5c, 0x80, 0x5c, 0x81, 0x5c, 0x82, 0x5c, 0x83, // value (nai-encoded)
+ // destination MIHF_ID TLV:
+ 0x02, 0x08, // type, length
+ 0x5c, 0x84, 0x5c, 0x85, 0x5c, 0x86, 0x5c, 0x87 // value (nai-encoded)
+ };
+ BOOST_CHECK(equal( mihPacket.data().begin(), mihPacket.data().end(), data ));
+ BOOST_CHECK_EQUAL(
+ mihPacket->src_mihfId().asINet4Address(),
+ INet4Address::from_string("128.129.130.131"));
+ BOOST_CHECK_EQUAL(
+ mihPacket->dst_mihfId().asINet4Address(),
+ INet4Address::from_string("132.133.134.135"));
+}
+
+
+BOOST_AUTO_UNIT_TEST(MIHPacket_create_inet6)
+{
+ MIHPacket mihPacket (MIHPacket::create());
+ // set some fields
+ mihPacket->fragmentNr() = 42;
+ mihPacket->transactionId() = 21;
+ mihPacket->src_mihfId().setINet6Address( INet6Address::from_string("::ffff:1.2.3.4"));
+ mihPacket->dst_mihfId().setINet6Address( INet6Address::from_string("::ffff:5.6.7.8"));
+ mihPacket.finalizeThis();
unsigned char data[] = {
- 0x10, 0x54, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04,
- 0x01, 0x00,
- 0x02, 0x00
+ // MIH header
+ 0x10, 0x54, 0x00, 0x00, 0x00, 0x15, 0x00, 0x44,
+ // source MIHF_ID TLV:
+ 0x01, 0x20, // type, 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
+ // 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, 0x05, 0x5c, 0x06, 0x5c, 0x07, 0x5c, 0x08
};
- BOOST_CHECK( equal( mihPacket.data().begin(), mihPacket.data().end(), data ));
+ BOOST_CHECK(equal( mihPacket.data().begin(), mihPacket.data().end(), data ));
+ BOOST_CHECK_EQUAL(
+ mihPacket->src_mihfId().asINet6Address(),
+ INet6Address::from_string("::ffff:1.2.3.4"));
+ BOOST_CHECK_EQUAL(
+ mihPacket->dst_mihfId().asINet6Address(),
+ INet6Address::from_string("::ffff:5.6.7.8") );
}
///////////////////////////////cc.e////////////////////////////////////////