- using std::size_t for ordinary integers, those that do not impose size constraints
- using uint32_t, uint16_t or uint_8_t for integers which require specific sizes
--- /dev/null
--- /dev/null
++
++Code Conventions
++=======================================
++This section describes the code conventions that must be followed when maintain
++this code.
++
++
++Data Types
++---------------------------------------
++
++Use std::string to represent array of characters.
++
++Use int32_t, int16_t and int8_t (and their unsigned couter parts) instead of
++int, short and char, respectively, when the variable or constant MUST have a
++specific size (e.g. like in the protocol headers). This documents that the
++variable have the given number of bits.
++
++Use std::size_t for regular integer numbers that do not require any specific
++size. Thus leaving the size difinition to the platform.
--- /dev/null
+#include <boost/assert.hpp>
+
+#include "configuration.h"
+
+using namespace std;
+
+//-----------------------------------------------------------------------------
+// Configuration
+//-----------------------------------------------------------------------------
+
+Configuration::Configuration() :
+ ConfigFileName( "" ),
+ LimitToNotify( 0 ),
+ Host_( "" ),
+ MinLimitToNotify( 0 ),
+ MaxLimitToNotify( 50 )
+{
+}
+
+Configuration::~Configuration()
+{
+}
+
+string Configuration::get_config_file_name() const
+{
+ return ConfigFileName;
+}
+
- void Configuration::set_config_file_name( const std::string& config_file_name )
++void Configuration::set_config_file_name( const std::string &config_file_name )
+{
+ BOOST_ASSERT( !config_file_name.empty() );
+
+ this->ConfigFileName = config_file_name;
+}
+
- uint32_t Configuration::get_limit_to_notify() const
++std::size_t Configuration::get_limit_to_notify() const
+{
+ return LimitToNotify;
+}
+
- void Configuration::set_limit_to_notify( const uint32_t limit_to_notify )
++void Configuration::set_limit_to_notify( const std::size_t limit_to_notify )
+{
+ BOOST_ASSERT( ( MinLimitToNotify <= limit_to_notify ) && ( limit_to_notify <= MaxLimitToNotify) );
+
+ this->LimitToNotify = limit_to_notify;
+}
+
+Host Configuration::get_host() const
+{
+ return Host_;
+}
+
+void Configuration::set_host( const Host& host )
+{
+ this->Host_ = host;
+}
+
--- /dev/null
+#ifndef CONFIGURATION_H
+#define CONFIGURATION_H
+
+#include <stdint.h>
+#include <string>
+
+#include "host.h"
+
+//-----------------------------------------------------------------------------
+// Configuration
+//-----------------------------------------------------------------------------
+
+class Configuration
+{
+public:
+ Configuration();
+ virtual ~Configuration();
+
+ std::string get_config_file_name() const;
- void set_config_file_name( const std::string& config_file_name );
++ void set_config_file_name( const std::string &config_file_name );
+
- uint32_t get_limit_to_notify() const;
- void set_limit_to_notify( const uint32_t limit_to_notify );
++ std::size_t get_limit_to_notify() const;
++ void set_limit_to_notify( const std::size_t limit_to_notify );
+
+ Host get_host() const;
+ void set_host( const Host& host );
+
+private:
+ std::string ConfigFileName;
- uint32_t LimitToNotify;
++ std::size_t LimitToNotify;
+ Host Host_;
+
- const uint32_t MinLimitToNotify;
- const uint32_t MaxLimitToNotify;
++ const std::size_t MinLimitToNotify;
++ const std::size_t MaxLimitToNotify;
+
+};
+
+#endif /* CONFIGURATION_H */
--- /dev/null
+#include <boost/assert.hpp>
+#include <fstream>
+#include <iostream>
+#include <iterator>
+
+#include "configurationreader.h"
+
+using namespace std;
+using namespace boost::program_options;
+
+//-----------------------------------------------------------------------------
+// ConfigurationReader
+//-----------------------------------------------------------------------------
+
+ConfigurationReader::ConfigurationReader() :
+ Config(),
+ VersionCmdStr( "version" ),
+ VersionCmdDesc( "Print the version string and exit." ),
+ HelpCmdStr( "help" ),
+ HelpCmdDesc( "Print this help and exit." ),
+ DefaultConfigFileName( "pingcheck.cfg" ),
+ ConfigFileCmdStr( "config-file" ),
+ ConfigFileCmdDesc( "Name of the configuration file." ),
+ DefaultLimitToNotify( 4 ),
+ LimitToNotifyCmdStr( "limit-to-notify" ),
+ LimitToNotifyCmdDesc( "Limit of host that have to be down in order to notify." ),
+ HostNameCmdStr( "host.name" ),
+ HostNameCmdDesc( "Host address" ),
+ DefaultHostInterval( 1 ),
+ HostIntervalCmdStr( "host.interval" ),
+ HostIntervalCmdDesc( "Interval between each ping to the host" )
+{
+}
+
+ConfigurationReader::~ConfigurationReader()
+{
+}
+
+bool ConfigurationReader::parse(
+ const int argc,
- char* argv[]
++ char *argv[]
+)
+{
+ BOOST_ASSERT( argc > 0 );
+ BOOST_ASSERT( argv != NULL );
+
+ variables_map vm;
+ bool command_line_processed = process_command_line( argc, argv, vm );
+ bool configuration_file_processed = process_configuration_file( vm );
+
+ bool input_processed = command_line_processed && configuration_file_processed;
+ if (input_processed)
+ {
+ return parse_configuration_options( vm );
+ }
+
+ return false;
+}
+
+Configuration ConfigurationReader::get_configuration() const
+{
+ return Config;
+}
+
+options_description ConfigurationReader::get_generic_options() const
+{
+ options_description options( "Generic options" );
+ options.add_options()
+ ( VersionCmdStr.c_str(), VersionCmdDesc.c_str() )
+ ( HelpCmdStr.c_str(), HelpCmdDesc.c_str() )
+ ( ConfigFileCmdStr.c_str(), value<string>()->default_value( DefaultConfigFileName ), ConfigFileCmdDesc.c_str() )
+ ;
+
+ return options;
+}
+
- bool ConfigurationReader::is_generic_options( const variables_map& vm ) const
++bool ConfigurationReader::is_generic_options( const variables_map &vm ) const
+{
+ bool is_help = vm.count( HelpCmdStr );
+ bool is_version = vm.count( VersionCmdStr );
+ bool is_a_generic_option = is_help || is_version;
+
+ return is_a_generic_option;
+}
+
+bool ConfigurationReader::parse_generic_options(
+ const variables_map& vm,
+ const options_description& visible_options
+)
+{
+ if ( vm.count( HelpCmdStr ) )
+ {
+ cout << visible_options << endl;
+ return true;
+ }
+
+ if ( vm.count( VersionCmdStr ) )
+ {
+ cout << PROJECT_NAME << " version " << VERSION_STRING << endl;
+ return true;
+ }
+
+ return false;
+}
+
+options_description ConfigurationReader::get_configuration_options() const
+{
+ options_description options( "Configuration" );
+ options.add_options()
- ( LimitToNotifyCmdStr.c_str(), value<int>()->default_value( DefaultLimitToNotify ), LimitToNotifyCmdDesc.c_str() )
++ ( LimitToNotifyCmdStr.c_str(), value<size_t>()->default_value( DefaultLimitToNotify ), LimitToNotifyCmdDesc.c_str() )
+ ( HostNameCmdStr.c_str(), value< string >(), HostNameCmdDesc.c_str() )
- ( HostIntervalCmdStr.c_str(), value< int >()->default_value( DefaultHostInterval ), HostIntervalCmdDesc.c_str() )
++ ( HostIntervalCmdStr.c_str(), value<size_t>()->default_value( DefaultHostInterval ), HostIntervalCmdDesc.c_str() )
+ ;
+
+ return options;
+}
+
- bool ConfigurationReader::parse_configuration_options( const variables_map& vm )
++bool ConfigurationReader::parse_configuration_options( const variables_map &vm )
+{
+ if ( vm.count( ConfigFileCmdStr ) )
+ {
+ string config_file_name = vm[ ConfigFileCmdStr ].as<string> ();
+ Config.set_config_file_name( config_file_name );
+
+ cout << ConfigFileCmdStr << "=" << config_file_name << endl;
+ }
+
+ if ( vm.count( LimitToNotifyCmdStr ) )
+ {
- uint32_t limit_to_notify = vm[ LimitToNotifyCmdStr ].as<int> ();
++ size_t limit_to_notify = vm[ LimitToNotifyCmdStr ].as<size_t> ();
+ Config.set_limit_to_notify( limit_to_notify );
+
+ cout << LimitToNotifyCmdStr << "=" << limit_to_notify << endl;
+ }
+
+ if ( vm.count( HostNameCmdStr ) )
+ {
+ string host_name = vm[ HostNameCmdStr ].as<string> ();
+ Host host = Config.get_host();
+ host.set_address( host_name );
+ Config.set_host( host );
+
+ cout << HostNameCmdStr << "=" << host_name << endl;
+ }
+
+ if ( vm.count( HostIntervalCmdStr ) )
+ {
- int host_interval = vm[ HostIntervalCmdStr ].as<int> ();
++ size_t host_interval = vm[ HostIntervalCmdStr ].as<size_t> ();
+ Host host = Config.get_host();
+ host.set_interval( host_interval );
+ Config.set_host( host );
+
+ cout << HostIntervalCmdStr << "=" << host_interval << endl;
+ }
+
+ return true;
+}
+
+bool ConfigurationReader::process_command_line(
+ const int argc,
- char* argv[],
- variables_map& vm
++ char *argv[],
++ variables_map &vm
+)
+{
+ try
+ {
+ options_description generic = get_generic_options();
+ options_description config = get_configuration_options();
+
+ options_description cmdline_options;
+ cmdline_options.add( generic ).add( config );
+
+ options_description visible( "Allowed options" );
+ visible.add( generic ).add( config );
+
+ positional_options_description p;
+ p.add( HostNameCmdStr.c_str(), -1 );
+ //p.add( HostIntervalCmdStr.c_str(), -1 );
+
+ store( command_line_parser( argc, argv ).
+ options( cmdline_options ).
+ positional( p ).run(), vm );
+ notify( vm );
+
+ if ( is_generic_options( vm ) )
+ {
+ parse_generic_options( vm, visible );
+
+ return false;
+ }
+
+ }
+ catch ( exception& e )
+ {
+ cout << e.what() << endl;
+ return false;
+ }
+
+ return true;
+}
+
- bool ConfigurationReader::process_configuration_file( variables_map& vm )
++bool ConfigurationReader::process_configuration_file( variables_map &vm )
+{
+ string config_file_name = "";
+ if ( parse_configuration_options( vm ) )
+ config_file_name = Config.get_config_file_name();
+
+ return process_configuration_file( config_file_name, vm );
+}
+
+bool ConfigurationReader::process_configuration_file(
- const string& config_file_name,
- variables_map& vm
++ const string &config_file_name,
++ variables_map &vm
+)
+{
+ BOOST_ASSERT( !config_file_name.empty() );
+
+ ifstream ifs( config_file_name.c_str() );
+ if ( !ifs )
+ {
+ cout << "Can not open " << config_file_name << " file\n";
+ return false;
+ }
+ else
+ {
+ options_description config = get_configuration_options();
+ options_description config_file_options;
+ config_file_options.add( config );
+
+ store( parse_config_file( ifs, config_file_options ), vm );
+ notify( vm );
+ }
+
+ return true;
+}
--- /dev/null
+#ifndef CONFIGURATIONREADER_H
+#define CONFIGURATIONREADER_H
+
+#include <string>
+#include <boost/program_options.hpp>
+
+#include "configuration.h"
+
+//-----------------------------------------------------------------------------
+// ConfigurationReader
+//-----------------------------------------------------------------------------
+
+class ConfigurationReader
+{
+public:
+ ConfigurationReader();
+ virtual ~ConfigurationReader();
+
+ bool parse(
+ const int argc,
- char* argv[]
++ char *argv[]
+ );
+ Configuration get_configuration() const;
+
+private:
+ boost::program_options::options_description get_generic_options() const;
+ bool is_generic_options(
- const boost::program_options::variables_map& vm
++ const boost::program_options::variables_map &vm
+ ) const;
+ bool parse_generic_options(
- const boost::program_options::variables_map& vm,
- const boost::program_options::options_description& visible_options
++ const boost::program_options::variables_map &vm,
++ const boost::program_options::options_description &visible_options
+ );
+
+ boost::program_options::options_description get_configuration_options() const;
+ bool parse_configuration_options(
- const boost::program_options::variables_map& vm
++ const boost::program_options::variables_map &vm
+ );
+
+ bool process_command_line(
+ const int argc,
- char* argv[],
- boost::program_options::variables_map& vm
++ char *argv[],
++ boost::program_options::variables_map &vm
+ );
+ bool process_configuration_file(
- boost::program_options::variables_map& vm
++ boost::program_options::variables_map &vm
+ );
+ bool process_configuration_file(
- const std::string& config_file_name,
- boost::program_options::variables_map& vm
++ const std::string &config_file_name,
++ boost::program_options::variables_map &vm
+ );
+
+private:
+ Configuration Config;
+
+ const std::string VersionCmdStr;
+ const std::string VersionCmdDesc;
+ const std::string HelpCmdStr;
+ const std::string HelpCmdDesc;
+ const std::string DefaultConfigFileName;
+ const std::string ConfigFileCmdStr;
+ const std::string ConfigFileCmdDesc;
- const uint32_t DefaultLimitToNotify;
++ const std::size_t DefaultLimitToNotify;
+ const std::string LimitToNotifyCmdStr;
+ const std::string LimitToNotifyCmdDesc;
+ const std::string HostNameCmdStr;
+ const std::string HostNameCmdDesc;
- const uint32_t DefaultHostInterval;
++ const std::size_t DefaultHostInterval;
+ const std::string HostIntervalCmdStr;
+ const std::string HostIntervalCmdDesc;
+
+};
+
+#endif /* CONFIGURATIONREADER_H */
--- /dev/null
+#include <boost/assert.hpp>
- #include <climits>
++#include <limits>
+
+#include "host.h"
+
+//-----------------------------------------------------------------------------
+// Host
+//-----------------------------------------------------------------------------
+
+Host::Host( std::string address ) :
+ Address( address ),
+ Port( 0 ),
+ Interval( 0 ),
+ Options()
+{
+}
+
+Host::~Host()
+{
+}
+
+std::string Host::get_address() const
+{
+ return Address;
+}
+
+void Host::set_address( const std::string& address )
+{
+ BOOST_ASSERT( !address.empty() );
+
+ this->Address = address;
+}
+
+uint16_t Host::get_port() const
+{
+ return Port;
+}
+
+void Host::set_port( const uint16_t port )
+{
- BOOST_ASSERT( ( 0 < port ) && ( port < USHRT_MAX ) );
++ BOOST_ASSERT( ( 0 < port ) && ( port < std::numeric_limits<uint16_t>::max() ) );
+
+ this->Port = port;
+}
+
- uint32_t Host::get_interval() const
++std::size_t Host::get_interval() const
+{
+ return Interval;
+}
+
- void Host::set_interval( const uint32_t interval )
++void Host::set_interval( const std::size_t interval )
+{
- BOOST_ASSERT( ( 0 < interval ) && ( interval < UINT_MAX ) );
++ BOOST_ASSERT( ( 0 < interval ) && ( interval < std::numeric_limits<std::size_t>::max() ) );
+
+ this->Interval = interval;
+}
+
+std::vector<std::string> Host::get_options() const
+{
+ return Options;
+}
+
- void Host::set_options( const std::vector<std::string>& options )
++void Host::set_options( const std::vector<std::string> &options )
+{
+ this->Options = options;
+}
--- /dev/null
+#ifndef HOST_H
+#define HOST_H
+
++#include <stdint.h>
+#include <string>
+#include <vector>
+
- #include <stdint.h>
-
+//-----------------------------------------------------------------------------
+// Host
+//-----------------------------------------------------------------------------
+
+class Host
+{
+public:
+ Host( std::string address );
+ virtual ~Host();
+
+ std::string get_address() const;
+ void set_address( const std::string& address );
+
+ uint16_t get_port() const;
+ void set_port( const uint16_t port );
+
- uint32_t get_interval() const;
- void set_interval( const uint32_t interval );
++ std::size_t get_interval() const;
++ void set_interval( const std::size_t interval );
+
+ std::vector<std::string> get_options() const;
- void set_options( const std::vector<std::string>& options );
++ void set_options( const std::vector<std::string> &options );
+
+private:
+ std::string Address;
+ uint16_t Port;
- uint32_t Interval;
++ std::size_t Interval;
+ std::vector<std::string> Options;
+
+};
+
+#endif /* HOST_H */
--- /dev/null
+#include "ipv4header.h"
+
+//-----------------------------------------------------------------------------
+// Ipv4Header
+//-----------------------------------------------------------------------------
+
+Ipv4Header::Ipv4Header()
+{
+ std::fill( Rep, Rep + sizeof(Rep), 0 );
+}
+
+uint8_t Ipv4Header::get_version() const
+{
+ return (Rep[ 0 ] >> 4) & 0xF;
+}
+
+uint16_t Ipv4Header::get_header_length() const
+{
+ return (Rep[ 0 ] & 0xF) * 4;
+}
+
+uint8_t Ipv4Header::get_type_of_service() const
+{
+ return Rep[ 1 ];
+}
+
+uint16_t Ipv4Header::get_total_length() const
+{
+ return decode( 2, 3 );
+}
+
+uint16_t Ipv4Header::get_identification() const
+{
+ return decode( 4, 5 );
+}
+
+bool Ipv4Header::dont_fragment() const
+{
+ return (Rep[ 6 ] & 0x40) != 0;
+}
+
+bool Ipv4Header::have_more_fragments() const
+{
+ return (Rep[ 6 ] & 0x20) != 0;
+}
+
+uint16_t Ipv4Header::get_fragment_offset() const
+{
+ return decode( 6, 7 ) & 0x1FFF;
+}
+
- unsigned int Ipv4Header::get_time_to_live() const
++uint8_t Ipv4Header::get_time_to_live() const
+{
+ return Rep[ 8 ];
+}
+
+uint8_t Ipv4Header::get_protocol() const
+{
+ return Rep[ 9 ];
+}
+
+uint16_t Ipv4Header::get_header_checksum() const
+{
+ return decode( 10, 11 );
+}
+
+boost::asio::ip::address_v4 Ipv4Header::get_source_address() const
+{
+ boost::asio::ip::address_v4::bytes_type bytes = { {
+ Rep[ 12 ],
+ Rep[ 13 ],
+ Rep[ 14 ],
+ Rep[ 15 ] } };
+ return boost::asio::ip::address_v4( bytes );
+}
+
+boost::asio::ip::address_v4 Ipv4Header::get_destination_address() const
+{
+ boost::asio::ip::address_v4::bytes_type bytes = { {
+ Rep[ 16 ],
+ Rep[ 17 ],
+ Rep[ 18 ],
+ Rep[ 19 ] } };
+ return boost::asio::ip::address_v4( bytes );
+}
+
+std::istream& operator>>(
+ std::istream &is,
+ Ipv4Header &header
+)
+{
+ is.read( reinterpret_cast<char*> ( header.Rep ), 20 );
+ if ( header.get_version() != 4 )
+ is.setstate( std::ios::failbit );
+ std::streamsize options_length = header.get_header_length() - 20;
+ if ( options_length < 0 || options_length > 40 )
+ is.setstate( std::ios::failbit );
+ else
+ is.read( reinterpret_cast<char*> ( header.Rep ) + 20, options_length );
+ return is;
+}
+
+uint16_t Ipv4Header::decode( int a, int b ) const
+{
+ return ((Rep[ a ] << 8) + Rep[ b ]);
+}
--- /dev/null
+#ifndef IPV4_HEADER_HPP
+#define IPV4_HEADER_HPP
+
+#include <algorithm>
+#include <boost/asio/ip/address_v4.hpp>
+#include <stdint.h>
+
+//-----------------------------------------------------------------------------
+// Ipv4Header
+//-----------------------------------------------------------------------------
+// IPv4 header format:
+//
+// 0 8 16 31
+// +-------+-------+---------------+------------------------------+ ---
+// | | | | | ^
+// |version|header | type of | total length in bytes | |
+// | (4) | length| service | | |
+// +-------+-------+---------------+-+-+-+------------------------+ |
+// | | | | | | |
+// | identification |0|D|M| fragment offset | |
+// | | |F|F| | |
+// +---------------+---------------+-+-+-+------------------------+ |
+// | | | | |
+// | time to live | protocol | header checksum | 20 bytes
+// | | | | |
+// +---------------+---------------+------------------------------+ |
+// | | |
+// | source IPv4 address | |
+// | | |
+// +--------------------------------------------------------------+ |
+// | | |
+// | destination IPv4 address | |
+// | | v
+// +--------------------------------------------------------------+ ---
+// | | ^
+// | | |
+// / options (if any) / 0 - 40
+// / / bytes
+// | | |
+// | | v
+// +--------------------------------------------------------------+ ---
+//
+//-----------------------------------------------------------------------------
+
+class Ipv4Header
+{
+public:
+ Ipv4Header();
+
+ uint8_t get_version() const;
+ uint16_t get_header_length() const;
+ uint8_t get_type_of_service() const;
+ uint16_t get_total_length() const;
+ uint16_t get_identification() const;
+
+ bool dont_fragment() const;
+ bool have_more_fragments() const;
+ uint16_t get_fragment_offset() const;
- unsigned int get_time_to_live() const;
++ uint8_t get_time_to_live() const;
+ uint8_t get_protocol() const;
+ uint16_t get_header_checksum() const;
+
+ boost::asio::ip::address_v4 get_source_address() const;
+ boost::asio::ip::address_v4 get_destination_address() const;
+
+ friend std::istream& operator>>(
+ std::istream &is,
+ Ipv4Header &header
+ );
+
+private:
+ uint16_t decode( int a, int b ) const;
+
+ uint8_t Rep[ 60 ];
+};
+
+#endif // IPV4_HEADER_H