senf::EthernetPacket eth (senf::EthernetPacket::create(senf::noinit));
isock.read(eth.data(),0u);
GREPacket gre (senf::GREPacket::createBefore(eth));
- gre.finalize();
+ gre.finalizeAll();
osock.write(gre.data());
}
}
vlan->cfi() = true;
vlan->vlanId() = 0x234u;
- eth.finalize();
+ eth.finalizeAll();
BOOST_CHECK_EQUAL(eth->type_length(), 0x8100u);
BOOST_CHECK_EQUAL(vlan->type(), 0u);
senf::IPv4Packet ip (senf::IPv4Packet::createAfter(vlan));
- eth.finalize();
+ eth.finalizeAll();
BOOST_CHECK_EQUAL(vlan->type(), 0x0800u);
}
senf::LlcSnapPacket llcsnap (senf::LlcSnapPacket::createAfter(eth));
senf::DataPacket payload (senf::DataPacket::createAfter(
llcsnap, std::string("Hello, world!")));
- eth.finalize();
+ eth.finalizeAll();
BOOST_CHECK_EQUAL( eth->type_length(), 8u + 13u);
BOOST_CHECK_EQUAL( llcsnap->dsap(), 0xaa );
BOOST_CHECK_EQUAL( llcsnap->type_length(), 0u);
senf::IPv4Packet ip (senf::IPv4Packet::createAfter(llcsnap));
- eth.finalize();
+ eth.finalizeAll();
BOOST_CHECK_EQUAL(llcsnap->type_length(), 0x0800u);
}
BOOST_CHECK( ! ip->validateChecksum() );
- ip.finalize();
+ ip.finalizeAll();
BOOST_CHECK_EQUAL( ip->length(), 28u );
BOOST_CHECK_EQUAL( ip->protocol(), 17u );
BOOST_CHECK_EQUAL( ip->checksum(), 0xbad2 );
// Check, that the checksum field is correctly skipped
- ip.finalize();
+ ip.finalizeAll();
BOOST_CHECK_EQUAL( ip->checksum(), 0xbad2 );
BOOST_CHECK( ip->validateChecksum() );
senf::EthernetPacket eth (senf::EthernetPacket::createAfter(llcsnap));
senf::DataPacket payload (senf::DataPacket::createAfter(
eth, std::string("Hello, world!")));
- llcsnap.finalize();
+ llcsnap.finalizeAll();
BOOST_CHECK_EQUAL( llcsnap->dsap(), 0xaa );
BOOST_CHECK_EQUAL( llcsnap->ssap(), 0xaa );
// validates, since the checksum is 0 and thus ignored !
BOOST_CHECK( udp->validateChecksum() );
- ip.finalize();
+ ip.finalizeAll();
BOOST_CHECK_EQUAL_COLLECTIONS( data, data+sizeof(data),
ip.data().begin(), ip.data().end() );
BOOST_CHECK( udp->validateChecksum() );
};
senf::DataPacket payload (senf::DataPacket::createAfter(ip, payload_data));
- sec.finalize();
+ sec.finalizeAll();
unsigned char sec_data[] = {
0x3e, 0xb0, 0x77, 0x00, 0x00, 0xc3, 0x00, 0x00,
TestTLVPacket tlvPacket (TestTLVPacket::create());
tlvPacket->type() = 42u;
DataPacket::createAfter( tlvPacket, payload );
- tlvPacket.finalize();
+ tlvPacket.finalizeAll();
BOOST_CHECK_EQUAL( tlvPacket->type(), 42u);
BOOST_CHECK_EQUAL( tlvPacket->length(), 13u);
TestTLVPacket tlvPacket (TestTLVPacket::create());
tlvPacket->type() = 42u;
DataPacket::createAfter( tlvPacket, payload );
- tlvPacket.finalize();
+ tlvPacket.finalizeAll();
BOOST_CHECK_EQUAL( tlvPacket->type(), 42u );
BOOST_CHECK_EQUAL( tlvPacket->length(), payload.size() );
payload = std::string("This is a short string with less than 127 characters. That's all.");
DataPacket::createAfter( tlvPacket, payload );
- tlvPacket.finalize();
+ tlvPacket.finalizeAll();
BOOST_CHECK_EQUAL( tlvPacket->type(), 42u );
BOOST_CHECK_EQUAL( tlvPacket->length(), payload.size() );
TLVFixPacketType tlvPacket (TLVFixPacketType::create());
tlvPacket->type() = 42u;
DataPacket::createAfter( tlvPacket, payload );
- tlvPacket.finalize();
+ tlvPacket.finalizeAll();
BOOST_CHECK_EQUAL( tlvPacket->type(), 42u);
BOOST_CHECK_EQUAL( tlvPacket->length(), 13u);
tlvPacket->type() = 42u;
DataPacket payload (DataPacket::createAfter( tlvPacket, max_value+1));
//DataPacket::createAfter( payload, 1); // this is one byte to much.
- BOOST_CHECK_THROW( tlvPacket.finalize(), UnsuportedTLVPacketException);
+ BOOST_CHECK_THROW( tlvPacket.finalizeAll(), UnsuportedTLVPacketException);
}
BOOST_AUTO_UNIT_TEST(TLVFixPacket_create_invalid_packet)
eth->source() = senf::MACAddress::from_string("00:11:22:33:44:55");
eth->destination() = senf::MACAddress::from_string("00:11:22:33:44:66");
- eth.finalize();
+ eth.finalizeAll();
\endcode
Again, realize, that \a eth, \a ip, \a udp and \a payload share the same internal packet
eth->source() = senf::MACAddress::from_string("00:11:22:33:44:55");
eth->destination() = senf::MACAddress::from_string("00:11:22:33:44:66");
- eth.finalize();
+ eth.finalizeAll();
\endcode
As seen above, packet fields are accessed using the <tt>-></tt> operator whereas other packet
- facilities (like \c finalize()) are directly accessed using the member operator. The field
- values are simply set using appropriately named accessors. As a last step, the \c finalize()
+ facilities (like \c finalizeAll()) are directly accessed using the member operator. The field
+ values are simply set using appropriately named accessors. As a last step, the \c finalizeAll()
call will update all calculated fields (fields like next-protocol, header or payload length,
checksums etc). Now the packet is ready. We may now send it out using a packet socket
return ptr() == other.ptr();
}
-prefix_ void senf::Packet::finalize()
- const
+prefix_ void senf::Packet::finalizeThis()
{
- last(); // Make sure the packet is complete
- ptr()->finalize();
+ ptr()->finalizeThis();
+}
+
+prefix_ void senf::Packet::finalizeTo(Packet other)
+{
+ ptr()->finalizeTo(other.ptr());
+}
+
+prefix_ void senf::Packet::finalizeAll()
+{
+ ptr()->finalizeTo(last().ptr());
}
prefix_ void senf::Packet::dump(std::ostream & os)
return first().as<OtherPacket>();
}
+template <class Other>
+prefix_ void senf::Packet::finalizeTo()
+{
+ Packet p (find<Other>(nothrow));
+ ptr()->finalizeTo(p ? p.ptr() : last().ptr());
+}
+
///////////////////////////////////////////////////////////////////////////
// senf::ConcretePacket<PacketType>
This is an alias for boolean_test() which is called
when using a packet in a boolean context. */
- void finalize() const; ///< Update calculated fields
+ void finalizeThis(); ///< Update calculated fields
/**< This call will update all calculated fields of the
- packet after it has been created or changed. This
- includes checksums, payload size fields or other
- fields, which can be set from other information in the
- packet. Each concrete packet type should document,
- which fields are set by finalize().
+ packet. This includes checksums, payload size fields or
+ other fields, which can be set from other information
+ in the packet. Each concrete packet type should
+ document, which fields are set by finalize().
+
+ finalizeThis() will \e only process the current
+ header. Even if only changing fields in this protocol,
+ depending on the protocol it may not be enough to
+ finalize this header only. See the packet type
+ documentation. */
+
+ template <class Other>
+ void finalizeTo(); ///< Update calculated fields
+ /**< This call will update all calculated fields of the
+ packet. This includes checksums, payload size fields or
+ other fields, which can be set from other information
+ in the packet. Each concrete packet type should
+ document, which fields are set by finalize().
+
+ finalizeTo() will automatically process all
+ packets/headers/interpreters from the first occurrence
+ of packet type \a Other backwards up to \c this. */
+
+ void finalizeTo(Packet other); ///< Update calculated fields
+ /**< This call will update all calculated fields of the
+ packet. This includes checksums, payload size fields or
+ other fields, which can be set from other information
+ in the packet. Each concrete packet type should
+ document, which fields are set by finalize().
+
+ finalizeAll(other) will automatically process all
+ packets/headers/interpreters from \a other backwards up
+ to \c this. */
+
+ void finalizeAll(); ///< Update calculated fields
+ /**< This call will update all calculated fields of the
+ packet. This includes checksums, payload size fields or
+ other fields, which can be set from other information
+ in the packet. Each concrete packet type should
+ document, which fields are set by finalize().
- finalize() will automatically process all
+ finalizeAll() will automatically process all
packets/headers/interpreters from the end of the chain
backwards up to \c this. */
packet.dump(s);
BOOST_CHECK_EQUAL( s.str(), "BarPacket:\ntype: 0\nlength: 0\n" );
- packet.finalize();
+ packet.finalizeAll();
BOOST_CHECK_EQUAL( packet.last().as<BarPacket>()->type(),
BarPacket::type::parser::type_t::value_type(-1) );
packet.last().append(FooPacket::create());
- packet.finalize();
+ packet.finalizeAll();
BOOST_CHECK_EQUAL( packet.find<BarPacket>()->type(), 1u );
BOOST_CHECK( packet.factory() == FooPacket::factory() );
i->v_dump(os);
}
-prefix_ void senf::PacketInterpreterBase::finalize()
+prefix_ void senf::PacketInterpreterBase::finalizeThis()
{
- for (ptr i (last()) ; i.get() != this ; i = i->prev())
- i->v_finalize();
v_finalize();
}
+prefix_ void senf::PacketInterpreterBase::finalizeTo(ptr other)
+{
+ for (ptr i (other); i.get() != this && i.get(); i = i->prev())
+ i->finalizeThis();
+ finalizeThis();
+}
+
///////////////////////////////////////////////////////////////////////////
// senf::PacketInterpreterBase::Factory
///@{
optional_range nextPacketRange();
- void finalize();
+ void finalizeThis();
+ void finalizeTo(ptr other);
void dump(std::ostream & os);
TypeIdValue typeId();
factory_t factory();