Packets: Extend finalize() API
g0dil [Mon, 22 Sep 2008 19:33:23 +0000 (19:33 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@914 270642c3-0616-0410-b53a-bc976706d245

14 files changed:
HowTos/NewPacket/Mainpage.dox
Packets/DefaultBundle/EthernetPacket.test.cc
Packets/DefaultBundle/IPv4Packet.test.cc
Packets/DefaultBundle/LlcSnapPacket.test.cc
Packets/DefaultBundle/UDPPacket.test.cc
Packets/MPEGDVBBundle/MPESection.test.cc
Packets/MPEGDVBBundle/TLVPacket.test.cc
Packets/Mainpage.dox
Packets/Packet.cci
Packets/Packet.cti
Packets/Packet.hh
Packets/Packet.test.cc
Packets/PacketInterpreter.cc
Packets/PacketInterpreter.hh

index 28403e0..0547543 100644 (file)
             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());
         }
     }
index 3644b51..4c25433 100644 (file)
@@ -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);
 }
 
index b2a16e6..423e19f 100644 (file)
@@ -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() );
index 6d9ec74..8f2bb4e 100644 (file)
@@ -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 );
index ca2f000..6df9409 100644 (file)
@@ -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() );
index 91ba677..311c6da 100644 (file)
@@ -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,
index e454827..5fd157f 100644 (file)
@@ -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)
index 6ae0de7..cfa8e30 100644 (file)
     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
 
index f02dabd..35bd931 100644 (file)
@@ -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)
index 6dec365..fac31c0 100644 (file)
@@ -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>
 
index f08a996..af45ff2 100644 (file)
@@ -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. */
 
index 937901c..2da754d 100644 (file)
@@ -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() );
index 3d8a382..466ba1f 100644 (file)
@@ -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
 
index b42cb19..24f29c2 100644 (file)
@@ -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();