Split the TcpHeader implementation and header
authorGuilherme Maciel Ferreira <guilherme.maciel.ferreira@gmail.com>
Fri, 22 Jul 2011 02:16:37 +0000 (23:16 -0300)
committerGuilherme Maciel Ferreira <guilherme.maciel.ferreira@gmail.com>
Fri, 22 Jul 2011 02:16:37 +0000 (23:16 -0300)
src/CMakeLists.txt
src/tcp/tcpheader.cpp [new file with mode: 0644]
src/tcp/tcpheader.h

index d601e4b..0f02a6a 100644 (file)
@@ -52,6 +52,7 @@ set(SOURCES
     ip/ipv4header.cpp
     link/linkstatusanalyzer.cpp
     link/statusnotifiercommand.cpp
+    tcp/tcpheader.cpp
     tcp/tcppinger.cpp
     main.cpp
 )
diff --git a/src/tcp/tcpheader.cpp b/src/tcp/tcpheader.cpp
new file mode 100644 (file)
index 0000000..f1cb206
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+The software in this package is distributed under the GNU General
+Public License version 2 (with a special exception described below).
+
+A copy of GNU General Public License (GPL) is included in this distribution,
+in the file COPYING.GPL.
+
+As a special exception, if other files instantiate templates or use macros
+or inline functions from this file, or you compile this file and link it
+with other works to produce a work based on this file, this file
+does not by itself cause the resulting work to be covered
+by the GNU General Public License.
+
+However the source code for this file must still be made available
+in accordance with section (3) of the GNU General Public License.
+
+This exception does not invalidate any other reasons why a work based
+on this file might be covered by the GNU General Public License.
+*/
+#include "tcp/tcpheader.h"
+
+#include <cstring>
+#include <netinet/in.h>
+#include <sys/socket.h>
+
+#include <algorithm>
+
+#include "ip/pseudoipv4header.h"
+
+using namespace std;
+
+//-----------------------------------------------------------------------------
+// TcpHeader
+//-----------------------------------------------------------------------------
+
+TcpHeader::TcpHeader()
+{
+    fill( rep_, rep_ + sizeof(rep_), 0 );
+}
+
+uint16_t TcpHeader::source_port() const
+{
+    return decode( 0, 1 );
+}
+
+uint16_t TcpHeader::destination_port() const
+{
+    return decode( 2, 3 );
+}
+
+uint32_t TcpHeader::sequence_number() const
+{
+    uint32_t seq_num = (uint32_t) (
+            rep_[4] << 24 |
+            rep_[5] << 16 |
+            rep_[6] << 8 |
+            rep_[7]
+    );
+
+    return seq_num;
+}
+
+uint32_t TcpHeader::acknowledgment_number() const
+{
+    uint32_t ack_num = (uint32_t) (
+            rep_[8] << 24 |
+            rep_[9] << 16 |
+            rep_[10] << 8 |
+            rep_[11]
+    );
+
+    return ack_num;
+}
+
+uint8_t TcpHeader::header_length() const
+{
+    return (rep_[12] & 0xF0) >> 4;
+}
+
+bool TcpHeader::congestion_window_reduced() const
+{
+    return (rep_[13] & 0x80);
+}
+
+bool TcpHeader::ecn_echo() const
+{
+    return (rep_[13] & 0x40);
+}
+
+bool TcpHeader::urgent() const
+{
+    return (rep_[13] & 0x20);
+}
+
+bool TcpHeader::acknowledgment() const
+{
+    return (rep_[13] & 0x10);
+}
+
+bool TcpHeader::push() const
+{
+    return (rep_[13] & 0x08);
+}
+
+bool TcpHeader::reset() const
+{
+    return (rep_[13] & 0x04);
+}
+
+bool TcpHeader::synchronize() const
+{
+    return (rep_[13] & 0x02);
+}
+
+bool TcpHeader::finish() const
+{
+    return (rep_[13] & 0x01);
+}
+
+uint16_t TcpHeader::window_size() const
+{
+    return decode( 14, 15 );
+}
+
+uint16_t TcpHeader::checksum() const
+{
+    return decode( 16, 17 );
+}
+
+uint16_t TcpHeader::calculate_tcp_checksum(
+        const uint32_t src_addr,
+        const uint32_t dest_addr,
+        const char* tcp_payload_data,
+        const uint16_t tcp_payload_size_in_bytes )
+{
+    checksum( 0 );
+    uint16_t tcp_header_size_in_bytes = 20;
+    uint16_t tcp_segment_size_in_bytes = static_cast< uint16_t > (
+            tcp_header_size_in_bytes + tcp_payload_size_in_bytes
+    );
+
+    PseudoIpv4Header pseudo_header;
+    pseudo_header.source_address = htonl(src_addr);
+    pseudo_header.destination_address = htonl(dest_addr);
+    pseudo_header.zero_byte = 0;
+    pseudo_header.protocol = IPPROTO_TCP;
+    pseudo_header.header_length = htons( tcp_segment_size_in_bytes );
+
+    int pseudo_header_size_in_bytes = sizeof(PseudoIpv4Header);
+
+    uint8_t tcp_buffer[65536];
+    memset( tcp_buffer, 0, sizeof(tcp_buffer) );
+
+    memcpy( tcp_buffer, &pseudo_header, pseudo_header_size_in_bytes );
+    memcpy( tcp_buffer + pseudo_header_size_in_bytes, rep_,
+            tcp_header_size_in_bytes );
+    memcpy( tcp_buffer + pseudo_header_size_in_bytes + tcp_header_size_in_bytes,
+            tcp_payload_data, tcp_payload_size_in_bytes );
+
+    uint16_t cksum = calculate_checksum(
+            (uint16_t *) tcp_buffer,
+            pseudo_header_size_in_bytes + tcp_header_size_in_bytes + tcp_payload_size_in_bytes
+    );
+
+    cksum = ntohs( cksum );
+
+    return cksum;
+}
+
+void TcpHeader::source_port( const uint16_t port )
+{
+    encode( 0, 1, port );
+}
+
+void TcpHeader::destination_port( const uint16_t port )
+{
+    encode( 2, 3, port );
+}
+
+void TcpHeader::sequence_number( const uint32_t seq_num )
+{
+    rep_[4] = (uint8_t) (seq_num >> 24) & 0xFF;
+    rep_[5] = (uint8_t) (seq_num >> 16) & 0xFF;
+    rep_[6] = (uint8_t) (seq_num >> 8) & 0xFF;
+    rep_[7] = (uint8_t) seq_num & 0xFF;
+}
+
+void TcpHeader::acknowledgment_number( const uint32_t ack_num )
+{
+    rep_[8] = (uint8_t) (ack_num >> 24) & 0xFF;
+    rep_[9] = (uint8_t) (ack_num >> 16) & 0xFF;
+    rep_[10] = (uint8_t) (ack_num >> 8) & 0xFF;
+    rep_[11] = (uint8_t) ack_num & 0xFF;
+}
+
+void TcpHeader::header_length( const uint8_t offset )
+{
+    uint8_t high_nimble = static_cast<uint8_t>( ( offset << 4 ) & 0xF0 );
+    uint8_t lower_nimble = ( rep_[12] & 0x0F );
+    rep_[12] = high_nimble | lower_nimble;
+}
+
+void TcpHeader::congestion_window_reduced( bool bit )
+{
+    rep_[13] |= bit ? 0x80 : 0x0;
+}
+
+void TcpHeader::ecn_echo( bool bit )
+{
+    rep_[13] |= bit ? 0x40 : 0x0;
+}
+
+void TcpHeader::urgent( bool bit )
+{
+    rep_[13] |= bit ? 0x20 : 0x0;
+}
+
+void TcpHeader::acknowledgment( bool bit )
+{
+    rep_[13] |= bit ? 0x10 : 0x0;
+}
+
+void TcpHeader::push( bool bit )
+{
+    rep_[13] |= bit ? 0x08 : 0x0;
+}
+
+void TcpHeader::reset( bool bit )
+{
+    rep_[13] |= bit ? 0x04 : 0x0;
+}
+
+void TcpHeader::synchronize( bool bit )
+{
+    rep_[13] |= bit ? 0x02 : 0x0;
+}
+
+void TcpHeader::finish( bool bit )
+{
+    rep_[13] |= bit ? 0x01 : 0x0;
+}
+
+void TcpHeader::window_size( const uint16_t wnd_size )
+{
+    encode( 14, 15, wnd_size );
+}
+
+void TcpHeader::checksum( const uint16_t sum )
+{
+    encode( 16, 17, sum );
+}
+
+istream& operator>>( istream& is, TcpHeader& header )
+{
+    return is.read( reinterpret_cast< char* > ( header.rep_ ), 20 );
+}
+
+ostream& operator<<( ostream& os, const TcpHeader& header )
+{
+    return os.write( reinterpret_cast< const char* > ( header.rep_ ), 20 );
+}
+
+uint16_t TcpHeader::decode( int a, int b ) const
+{
+    return static_cast<uint16_t>( (rep_[a] << 8) + rep_[b] );
+}
+
+void TcpHeader::encode( int a, int b, const uint16_t n )
+{
+    rep_[a] = static_cast< uint8_t > ( n >> 8 );
+    rep_[b] = static_cast< uint8_t > ( n & 0xFF );
+}
+
+uint16_t TcpHeader::calculate_checksum( const uint16_t *word_array, int size )
+{
+    unsigned long cksum = 0;
+    while ( size > 1 )
+    {
+        cksum += *word_array++;
+        size -= sizeof(word_array[ 0 ]);
+    }
+    if ( size )
+    {
+        cksum += *(uint8_t*) word_array;
+    }
+
+    cksum = (cksum >> 16) + (cksum & 0xffff);
+    cksum += (cksum >> 16);
+
+    return (uint16_t) (~cksum);
+}
index 6062771..045c7c4 100644 (file)
@@ -20,12 +20,15 @@ on this file might be covered by the GNU General Public License.
 #ifndef TCP_HEADER_H
 #define TCP_HEADER_H
 
-#include <algorithm>
+#include <stdint.h>
 
-#include <boost/asio/ip/tcp_raw_protocol.hpp>
-
-#include "ip/pseudoipv4header.h"
+#include <istream>
+#include <ostream>
 
+//-----------------------------------------------------------------------------
+// TcpHeader
+//-----------------------------------------------------------------------------
+//
 // TCP Segment header.
 //
 // The wire format of a TCP header is:
@@ -65,259 +68,54 @@ on this file might be covered by the GNU General Public License.
 class TcpHeader
 {
 public:
-    TcpHeader()
-    {
-        std::fill( rep_, rep_ + sizeof(rep_), 0 );
-    }
-
-    uint16_t source_port() const
-    {
-        return decode( 0, 1 );
-    }
-
-    uint16_t destination_port() const
-    {
-        return decode( 2, 3 );
-    }
-
-    uint32_t sequence_number() const
-    {
-        uint32_t seq_num = (uint32_t) (
-                rep_[4] << 24 |
-                rep_[5] << 16 |
-                rep_[6] << 8 |
-                rep_[7]
-        );
-
-        return seq_num;
-    }
-
-    uint32_t acknowledgment_number() const
-    {
-        uint32_t ack_num = (uint32_t) (
-                rep_[8] << 24 |
-                rep_[9] << 16 |
-                rep_[10] << 8 |
-                rep_[11]
-        );
-
-        return ack_num;
-    }
-
-    uint8_t header_length() const
-    {
-        return (rep_[12] & 0xF0) >> 4;
-    }
-
-    bool congestion_window_reduced() const
-    {
-        return (rep_[13] & 0x80);
-    }
-
-    bool ecn_echo() const
-    {
-        return (rep_[13] & 0x40);
-    }
-
-    bool urgent() const
-    {
-        return (rep_[13] & 0x20);
-    }
-
-    bool acknowledgment() const
-    {
-        return (rep_[13] & 0x10);
-    }
-
-    bool push() const
-    {
-        return (rep_[13] & 0x08);
-    }
-
-    bool reset() const
-    {
-        return (rep_[13] & 0x04);
-    }
-
-    bool synchronize() const
-    {
-        return (rep_[13] & 0x02);
-    }
-
-    bool finish() const
-    {
-        return (rep_[13] & 0x01);
-    }
-
-    uint16_t window_size() const
-    {
-        return decode( 14, 15 );
-    }
-
-    uint16_t checksum() const
-    {
-        return decode( 16, 17 );
-    }
+    TcpHeader();
+
+    uint16_t source_port() const;
+    uint16_t destination_port() const;
+    uint32_t sequence_number() const;
+    uint32_t acknowledgment_number() const;
+    uint8_t header_length() const;
+    bool congestion_window_reduced() const;
+    bool ecn_echo() const;
+    bool urgent() const;
+    bool acknowledgment() const;
+    bool push() const;
+    bool reset() const;
+    bool synchronize() const;
+    bool finish() const;
+    uint16_t window_size() const;
+    uint16_t checksum() const;
 
     uint16_t calculate_tcp_checksum(
-            uint32_t src_addr,
-            uint32_t dest_addr,
-            char* tcp_payload_data,
-            uint16_t tcp_payload_size_in_bytes )
-    {
-        checksum( 0 );
-        uint16_t tcp_header_size_in_bytes = 20;
-        uint16_t tcp_segment_size_in_bytes = static_cast< uint16_t > (
-                tcp_header_size_in_bytes + tcp_payload_size_in_bytes
-        );
-
-        PseudoIpv4Header pseudo_header;
-        pseudo_header.source_address = htonl(src_addr);
-        pseudo_header.destination_address = htonl(dest_addr);
-        pseudo_header.zero_byte = 0;
-        pseudo_header.protocol = IPPROTO_TCP;
-        pseudo_header.header_length = htons( tcp_segment_size_in_bytes );
-
-        int pseudo_header_size_in_bytes = sizeof(PseudoIpv4Header);
-
-        uint8_t tcp_buffer[65536];
-        memset( tcp_buffer, 0, sizeof(tcp_buffer) );
-
-        memcpy( tcp_buffer, &pseudo_header, pseudo_header_size_in_bytes );
-        memcpy( tcp_buffer + pseudo_header_size_in_bytes, rep_,
-                tcp_header_size_in_bytes );
-        memcpy( tcp_buffer + pseudo_header_size_in_bytes + tcp_header_size_in_bytes,
-                tcp_payload_data, tcp_payload_size_in_bytes );
-
-        uint16_t cksum = calculate_checksum( (uint16_t *)
-            tcp_buffer,
-            pseudo_header_size_in_bytes + tcp_header_size_in_bytes + tcp_payload_size_in_bytes
-        );
-
-        cksum = ntohs( cksum );
-
-        return cksum;
-    }
-
-    void source_port( uint16_t port )
-    {
-        encode( 0, 1, port );
-    }
-
-    void destination_port( uint16_t port )
-    {
-        encode( 2, 3, port );
-    }
-
-    void sequence_number( uint32_t seq_num )
-    {
-        rep_[4] = (uint8_t) (seq_num >> 24) & 0xFF;
-        rep_[5] = (uint8_t) (seq_num >> 16) & 0xFF;
-        rep_[6] = (uint8_t) (seq_num >> 8) & 0xFF;
-        rep_[7] = (uint8_t) seq_num & 0xFF;
-    }
-
-    void acknowledgment_number( uint32_t ack_num )
-    {
-        rep_[8] = (uint8_t) (ack_num >> 24) & 0xFF;
-        rep_[9] = (uint8_t) (ack_num >> 16) & 0xFF;
-        rep_[10] = (uint8_t) (ack_num >> 8) & 0xFF;
-        rep_[11] = (uint8_t) ack_num & 0xFF;
-    }
-
-    void header_length( uint8_t offset )
-    {
-        uint8_t high_nimble = static_cast<uint8_t>( ( offset << 4 ) & 0xF0 );
-        uint8_t lower_nimble = ( rep_[12] & 0x0F );
-        rep_[12] = high_nimble | lower_nimble;
-    }
-
-    void congestion_window_reduced( bool bit )
-    {
-        rep_[13] |= bit ? 0x80 : 0x0;
-    }
-
-    void ecn_echo( bool bit )
-    {
-        rep_[13] |= bit ? 0x40 : 0x0;
-    }
-
-    void urgent( bool bit )
-    {
-        rep_[13] |= bit ? 0x20 : 0x0;
-    }
-
-    void acknowledgment( bool bit )
-    {
-        rep_[13] |= bit ? 0x10 : 0x0;
-    }
-
-    void push( bool bit )
-    {
-        rep_[13] |= bit ? 0x08 : 0x0;
-    }
-
-    void reset( bool bit )
-    {
-        rep_[13] |= bit ? 0x04 : 0x0;
-    }
-
-    void synchronize( bool bit )
-    {
-        rep_[13] |= bit ? 0x02 : 0x0;
-    }
-
-    void finish( bool bit )
-    {
-        rep_[13] |= bit ? 0x01 : 0x0;
-    }
-
-    void window_size( uint16_t wnd_size )
-    {
-        encode( 14, 15, wnd_size );
-    }
-
-    void checksum( uint16_t sum )
-    {
-        encode( 16, 17, sum );
-    }
-
-    friend std::istream& operator>>( std::istream& is, TcpHeader& header )
-    {
-        return is.read( reinterpret_cast< char* > ( header.rep_ ), 20 );
-    }
-
-    friend std::ostream& operator<<( std::ostream& os, const TcpHeader& header )
-    {
-        return os.write( reinterpret_cast< const char* > ( header.rep_ ), 20 );
-    }
+            const uint32_t src_addr,
+            const uint32_t dest_addr,
+            const char* tcp_payload_data,
+            const uint16_t tcp_payload_size_in_bytes
+    );
+
+    void source_port( const uint16_t port );
+    void destination_port( const uint16_t port );
+    void sequence_number( const uint32_t seq_num );
+    void acknowledgment_number( const uint32_t ack_num );
+    void header_length( const uint8_t offset );
+    void congestion_window_reduced( bool bit );
+    void ecn_echo( bool bit );
+    void urgent( bool bit );
+    void acknowledgment( bool bit );
+    void push( bool bit );
+    void reset( bool bit );
+    void synchronize( bool bit );
+    void finish( bool bit );
+    void window_size( const uint16_t wnd_size );
+    void checksum( const uint16_t sum );
+
+    friend std::istream& operator>>( std::istream& is, TcpHeader& header );
+    friend std::ostream& operator<<( std::ostream& os, const TcpHeader& header );
 
 private:
-    uint16_t decode( int a, int b ) const
-    {
-        return static_cast<uint16_t>( (rep_[a] << 8) + rep_[b] );
-    }
-
-    void encode( int a, int b, uint16_t n )
-    {
-        rep_[a] = static_cast< uint8_t > ( n >> 8 );
-        rep_[b] = static_cast< uint8_t > ( n & 0xFF );
-    }
-
-    uint16_t calculate_checksum( uint16_t *word_array, int size )
-    {
-        unsigned long cksum = 0;
-        while ( size > 1 ) {
-            cksum += *word_array++;
-            size -= sizeof(word_array[ 0 ]);
-        }
-        if ( size )
-            cksum += *(uint8_t*) word_array;
-
-        cksum = (cksum >> 16) + (cksum & 0xffff);
-        cksum += (cksum >> 16);
-        return (uint16_t) (~cksum);
-    }
+    uint16_t decode( int a, int b ) const;
+    void encode( int a, int b, const uint16_t n );
+    uint16_t calculate_checksum( const uint16_t *word_array, int size );
 
     uint8_t rep_[60];
 };