Replaced the raw byte array by a MessagePayload object, this class provides methods...
authorGuilherme Maciel Ferreira <guilherme.maciel.ferreira@gmail.com>
Fri, 26 Aug 2011 01:07:17 +0000 (22:07 -0300)
committerGuilherme Maciel Ferreira <guilherme.maciel.ferreira@gmail.com>
Fri, 26 Aug 2011 01:07:17 +0000 (22:07 -0300)
src/ip/ipv4header.cpp
src/ip/ipv4header.h

index 22bca50..655063e 100644 (file)
@@ -8,8 +8,11 @@
 
 #include <limits>
 
+#include <boost/scoped_array.hpp>
+
 using namespace std;
 using boost::asio::ip::address_v4;
+using boost::scoped_array;
 
 //-----------------------------------------------------------------------------
 // Ipv4Header
@@ -17,19 +20,25 @@ using boost::asio::ip::address_v4;
 
 static const size_t Ipv4HeaderSizeInBytes = 20;
 
-Ipv4Header::Ipv4Header()
+Ipv4Header::Ipv4Header() :
+    Payload( Ipv4HeaderSizeInBytes )
 {
-    fill( Payload, Payload + sizeof(Payload), 0 );
 }
 
 uint8_t Ipv4Header::get_version() const
 {
-    return ( Payload[ 0 ] >> 4 ) & 0xF;
+    return ( Payload[ 0 ] >> 4 ) & 0x0F;
 }
 
 uint16_t Ipv4Header::get_header_length() const
 {
-    return static_cast<uint16_t>( (Payload[ 0 ] & 0xF) * 4 );
+    // The Internet Header Length tells the number of 32-bit words in the
+    // header. Since an IPv4 header may contain a variable number of options,
+    // this field specifies the size of the header (this also coincides with
+    // the offset to the data). The minimum value for this field is 5 (RFC 791),
+    // which is a length of 5×32 = 160 bits = 20 bytes. Being a 4-bit value,
+    // the maximum length is 15 words (15×32 bits) or 480 bits = 60 bytes.
+    return static_cast<uint16_t>( (Payload[ 0 ] & 0x0F) * 4 );
 }
 
 uint8_t Ipv4Header::get_type_of_service() const
@@ -39,12 +48,12 @@ uint8_t Ipv4Header::get_type_of_service() const
 
 uint16_t Ipv4Header::get_total_length() const
 {
-    return decode( 2, 3 );
+    return Payload.decode16( 2, 3 );
 }
 
 uint16_t Ipv4Header::get_identification() const
 {
-    return decode( 4, 5 );
+    return Payload.decode16( 4, 5 );
 }
 
 bool Ipv4Header::dont_fragment() const
@@ -59,7 +68,7 @@ bool Ipv4Header::more_fragments() const
 
 uint16_t Ipv4Header::get_fragment_offset() const
 {
-    return decode( 6, 7 ) & 0x1FFF;
+    return Payload.decode16( 6, 7 ) & 0x1FFF;
 }
 
 uint8_t Ipv4Header::get_time_to_live() const
@@ -74,29 +83,21 @@ uint8_t Ipv4Header::get_protocol() const
 
 uint16_t Ipv4Header::get_header_checksum() const
 {
-    return decode( 10, 11 );
+    return Payload.decode16( 10, 11 );
 }
 
 address_v4 Ipv4Header::get_source_address() const
 {
-    address_v4::bytes_type bytes = { {
-            Payload[ 12 ],
-            Payload[ 13 ],
-            Payload[ 14 ],
-            Payload[ 15 ]
-    } };
-    return address_v4( bytes );
+    uint32_t address = Payload.decode32( 12, 15 );
+
+    return address_v4( address );
 }
 
 address_v4 Ipv4Header::get_destination_address() const
 {
-    address_v4::bytes_type bytes = { {
-            Payload[ 16 ],
-            Payload[ 17 ],
-            Payload[ 18 ],
-            Payload[ 19 ]
-    } };
-    return address_v4( bytes );
+    uint32_t address = Payload.decode32( 16, 19 );
+
+    return address_v4( address );
 }
 
 istream &operator>>(
@@ -104,37 +105,32 @@ istream &operator>>(
         Ipv4Header &header
 )
 {
-    (void) is.read(
-            reinterpret_cast<char*> ( header.Payload ),
-            Ipv4HeaderSizeInBytes
-    );
+    // read the first 20 bytes (mandatory for IP header) from the input stream
+    // and stores in the buffer object
+    header.Payload.read( is );
 
     if ( header.get_version() != 4 )
+    {
         is.setstate( ios::failbit );
-    streamsize options_length =
-            (streamsize) header.get_header_length() -
-            Ipv4HeaderSizeInBytes;
-    if ( options_length < 0 || 40 < options_length )
+    }
+
+    // read the consecutive N bytes (for options field) from the input stream
+    // and stores in the buffer object
+    streamsize options_length = (streamsize) header.get_header_length() -
+                                Ipv4HeaderSizeInBytes;
+    if ( ( options_length < 0 ) || ( 40 < options_length ) )
     {
         is.setstate( ios::failbit );
     }
     else
     {
-        (void) is.read(
-                reinterpret_cast<char*> ( header.Payload ) +
-                Ipv4HeaderSizeInBytes,
-                options_length
-        );
-    }
+        scoped_array<uint8_t> options_data(new uint8_t[options_length]);
+        char *options_data_array = reinterpret_cast<char *>( options_data.get() );
 
-    return is;
-}
-
-uint16_t Ipv4Header::decode( int left_byte, int right_byte ) const
-{
-    uint32_t value = ( Payload[ left_byte ] << 8 ) + Payload[ right_byte ];
+        is.read( options_data_array, options_length );
 
-    BOOST_ASSERT( value <= numeric_limits<uint16_t>::max() );
+        header.Payload.append( options_data.get(), options_length );
+    }
 
-    return static_cast<uint16_t>( value );
+    return is;
 }
index 4f07b3e..f7811c5 100644 (file)
@@ -11,6 +11,8 @@
 
 #include <boost/asio/ip/address_v4.hpp>
 
+#include "host/messagepayload.h"
+
 //-----------------------------------------------------------------------------
 // Ipv4Header
 //-----------------------------------------------------------------------------
@@ -76,10 +78,7 @@ public:
     );
 
 private:
-    uint16_t decode( int left_byte, int right_byte ) const;
-
-private:
-    uint8_t Payload[ 60 ];
+    MessagePayload Payload;
 
 };