diff --git a/HowTos/NewPacket/Mainpage.dox b/HowTos/NewPacket/Mainpage.dox index 28403e0a175a04300c96c8cf6467875ce10f71c0..054754398b4185c3a93067243e39cbf9853c4bd8 100644 --- a/HowTos/NewPacket/Mainpage.dox +++ b/HowTos/NewPacket/Mainpage.dox @@ -939,7 +939,7 @@ 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()); } } diff --git a/Packets/DefaultBundle/EthernetPacket.test.cc b/Packets/DefaultBundle/EthernetPacket.test.cc index 3644b51eaf2a0798c3a8a6ced87ff7d1cd0643bd..4c25433c5746f1edeef4f708b361186b2ffd8d80 100644 --- a/Packets/DefaultBundle/EthernetPacket.test.cc +++ b/Packets/DefaultBundle/EthernetPacket.test.cc @@ -83,12 +83,12 @@ BOOST_AUTO_UNIT_TEST(ethernetPacket_create) 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); } @@ -101,7 +101,7 @@ BOOST_AUTO_UNIT_TEST(ethernetPacket_llcsnap) 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 ); @@ -111,7 +111,7 @@ BOOST_AUTO_UNIT_TEST(ethernetPacket_llcsnap) 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); } diff --git a/Packets/DefaultBundle/IPv4Packet.test.cc b/Packets/DefaultBundle/IPv4Packet.test.cc index b2a16e64cb43575ab8cb2a9925caf9df3c990561..423e19fe3721303cfa2bbc88ed55698ab89fae52 100644 --- a/Packets/DefaultBundle/IPv4Packet.test.cc +++ b/Packets/DefaultBundle/IPv4Packet.test.cc @@ -77,13 +77,13 @@ BOOST_AUTO_UNIT_TEST(ipV4Packet_create) 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() ); diff --git a/Packets/DefaultBundle/LlcSnapPacket.test.cc b/Packets/DefaultBundle/LlcSnapPacket.test.cc index 6d9ec748b25f4b5232614cf707087cefd17bb73b..8f2bb4ecb043c4b3351aecdf096a2fdbf4897081 100644 --- a/Packets/DefaultBundle/LlcSnapPacket.test.cc +++ b/Packets/DefaultBundle/LlcSnapPacket.test.cc @@ -59,7 +59,7 @@ BOOST_AUTO_UNIT_TEST(llcSnapPacket_ethernet) 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 ); diff --git a/Packets/DefaultBundle/UDPPacket.test.cc b/Packets/DefaultBundle/UDPPacket.test.cc index ca2f00087c64c68c6c349c92504bc000261bd447..6df940989adb88782cb9be2d88ff768cc5e4537d 100644 --- a/Packets/DefaultBundle/UDPPacket.test.cc +++ b/Packets/DefaultBundle/UDPPacket.test.cc @@ -73,7 +73,7 @@ BOOST_AUTO_UNIT_TEST(udpPacket_create) // 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() ); diff --git a/Packets/MPEGDVBBundle/MPESection.test.cc b/Packets/MPEGDVBBundle/MPESection.test.cc index 91ba6773ed10d42b2ac7045f96f128b5016cce1e..311c6da9b237f3d386d01518589a7bbb4fc55da1 100644 --- a/Packets/MPEGDVBBundle/MPESection.test.cc +++ b/Packets/MPEGDVBBundle/MPESection.test.cc @@ -164,7 +164,7 @@ BOOST_AUTO_UNIT_TEST(MPESection_create) }; 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, diff --git a/Packets/MPEGDVBBundle/TLVPacket.test.cc b/Packets/MPEGDVBBundle/TLVPacket.test.cc index e454827df80a24bac11880039f19456d8ffe2695..5fd157f667cbbf77f9d968dc5a9bbaf461ce33dc 100644 --- a/Packets/MPEGDVBBundle/TLVPacket.test.cc +++ b/Packets/MPEGDVBBundle/TLVPacket.test.cc @@ -94,7 +94,7 @@ BOOST_AUTO_UNIT_TEST(TLVPacket_create_packet_with_simple_length) 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); @@ -113,7 +113,7 @@ BOOST_AUTO_UNIT_TEST(TLVPacket_create_packet_with_extended_length) 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() ); @@ -123,7 +123,7 @@ BOOST_AUTO_UNIT_TEST(TLVPacket_create_packet_with_extended_length) 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() ); @@ -186,7 +186,7 @@ void test_TLVFixPacket_creating() 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); @@ -216,7 +216,7 @@ void test_invalid_TLVFixPacket_creating(boost::uint32_t max_value) 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) diff --git a/Packets/Mainpage.dox b/Packets/Mainpage.dox index 6ae0de7c6658cba78668d2511a6bdae565cd78f5..cfa8e30e9f6c49c35959e3025f0ab34897425029 100644 --- a/Packets/Mainpage.dox +++ b/Packets/Mainpage.dox @@ -201,7 +201,7 @@ 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 @@ -274,12 +274,12 @@ 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 diff --git a/Packets/Packet.cci b/Packets/Packet.cci index f02dabd3c3e63d3c9dbce05b5d0fd4d9552ea4fe..35bd9313e23c1910a5a6f888f87cc48eae4da03f 100644 --- a/Packets/Packet.cci +++ b/Packets/Packet.cci @@ -137,11 +137,19 @@ prefix_ bool senf::Packet::operator==(Packet other) 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) diff --git a/Packets/Packet.cti b/Packets/Packet.cti index 6dec36531d7ea9a7c1509f820f911a7f9804df93..fac31c02bc8ae28f1d29004da6dbdbb03e264dc4 100644 --- a/Packets/Packet.cti +++ b/Packets/Packet.cti @@ -128,6 +128,13 @@ prefix_ OtherPacket senf::Packet::first() 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> diff --git a/Packets/Packet.hh b/Packets/Packet.hh index f08a996a87bf4fa760ed9246ad9519476af3b1f0..af45ff2b5c53b5a6ba394892a50893bdafdc1246 100644 --- a/Packets/Packet.hh +++ b/Packets/Packet.hh @@ -330,15 +330,50 @@ namespace senf { 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. */ diff --git a/Packets/Packet.test.cc b/Packets/Packet.test.cc index 937901c977e6d7ca475dc3acb355789cb10d3b7c..2da754dfb4b45729ad52f0f43a7ade2a6ef3f526 100644 --- a/Packets/Packet.test.cc +++ b/Packets/Packet.test.cc @@ -159,11 +159,11 @@ BOOST_AUTO_UNIT_TEST(packet) 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() ); diff --git a/Packets/PacketInterpreter.cc b/Packets/PacketInterpreter.cc index 3d8a382e0c4fd2170bed976d14c7c0980fed0cc9..466ba1f6a2be9981310a63724e8c762f3e65b0fe 100644 --- a/Packets/PacketInterpreter.cc +++ b/Packets/PacketInterpreter.cc @@ -79,13 +79,18 @@ prefix_ void senf::PacketInterpreterBase::dump(std::ostream & os) 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 diff --git a/Packets/PacketInterpreter.hh b/Packets/PacketInterpreter.hh index b42cb190f088248d4a9b75467d6e231f5729c85a..24f29c223beb90e838269e19528b8f0f023cc1c3 100644 --- a/Packets/PacketInterpreter.hh +++ b/Packets/PacketInterpreter.hh @@ -166,7 +166,8 @@ namespace senf { ///@{ optional_range nextPacketRange(); - void finalize(); + void finalizeThis(); + void finalizeTo(ptr other); void dump(std::ostream & os); TypeIdValue typeId(); factory_t factory();