From 0680280ae07eb16a30040d4ee8f0a69de977775f Mon Sep 17 00:00:00 2001 From: Christian Herdtweck Date: Mon, 26 Jan 2015 17:34:11 +0100 Subject: [PATCH] rename IcmpPaketDistributor files to IcmpPacketDistributor (k --> ck) --- src/icmp/icmppacketdistributor.cpp | 266 ++++++++++++++++++++++++++++++++++++ src/icmp/icmppacketdistributor.h | 119 ++++++++++++++++ src/icmp/icmppaketdistributor.cpp | 266 ------------------------------------ src/icmp/icmppaketdistributor.h | 119 ---------------- 4 files changed, 385 insertions(+), 385 deletions(-) create mode 100644 src/icmp/icmppacketdistributor.cpp create mode 100644 src/icmp/icmppacketdistributor.h delete mode 100644 src/icmp/icmppaketdistributor.cpp delete mode 100644 src/icmp/icmppaketdistributor.h diff --git a/src/icmp/icmppacketdistributor.cpp b/src/icmp/icmppacketdistributor.cpp new file mode 100644 index 0000000..bfa090d --- /dev/null +++ b/src/icmp/icmppacketdistributor.cpp @@ -0,0 +1,266 @@ +/* + 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. + + Christian Herdtweck, Intra2net AG 2015 + */ + +#include "icmppaketdistributor.h" + +#include +#include +#include +#include +#include + +#include "boost_assert_handler.h" +#include "icmp/icmppacketfactory.h" + + +using I2n::Logger::GlobalLogger; +using boost::asio::ip::icmp; + +static const std::size_t SOCKET_BUFFER_SIZE = 65536; // 64kB + +typedef std::set::iterator PingerListIterator; + + +bool IcmpPacketDistributorInstanceIdentifierComparator::operator() ( + const DistributorInstanceIdentifier &a, + const DistributorInstanceIdentifier &b ) const +{ + if ( a.first == boost::asio::ip::icmp::v4() ) + { + if ( b.first == boost::asio::ip::icmp::v4() ) + return a.second < b.second; // v4 == v4 + else + BOOST_ASSERT( b.first == boost::asio::ip::icmp::v6() ); + return true; // a(v4) < b(b6) + } + else + { + BOOST_ASSERT( a.first == boost::asio::ip::icmp::v6() ); + + if ( b.first == boost::asio::ip::icmp::v4() ) + return false; // a(v6) > b(v4) + else + BOOST_ASSERT( b.first == boost::asio::ip::icmp::v6() ); + return a.second < b.second; // v6 == v6 + } +} + +//----------------------------------------------------------------------------- +// Definition of IcmpPacketDistributor +//----------------------------------------------------------------------------- + +map_type IcmpPacketDistributor::Instances; // initialize + + +IcmpPacketDistributorItem IcmpPacketDistributor::get_distributor( + const icmp::socket::protocol_type &protocol, + const std::string &network_interface, + const IoServiceItem io_serv ) +{ + DistributorInstanceIdentifier identifier(protocol, network_interface); + + // check if there is an instance for this protocol and interface + if ( Instances.count(identifier) == 0 ) + { // need to create an instance for this protocol and network interface + GlobalLogger.info() << "Creating IcmpPacketDistributor for interface " + << network_interface << std::endl; + IcmpPacketDistributorItem new_instance( new IcmpPacketDistributor( + protocol, network_interface, io_serv ) ); + Instances[identifier] = new_instance; + } + + BOOST_ASSERT( Instances.count(identifier) == 1 ); + + // return the one instance for this protocol and interface + return Instances[identifier]; +} + + +IcmpPacketDistributorItem IcmpPacketDistributor::get_distributor( + const icmp::socket::protocol_type &protocol, + const std::string &network_interface ) +{ + DistributorInstanceIdentifier identifier(protocol, network_interface); + + BOOST_ASSERT( Instances.count(identifier) == 1 ); + + // return the one instance for this protocol and interface + return Instances[identifier]; +} + + +IcmpPacketDistributor::IcmpPacketDistributor( + const icmp::socket::protocol_type &protocol, + const std::string &network_interface, + const IoServiceItem io_serv ): + Protocol( protocol ), + ReplyBuffer(), + PingerList() +{ + Socket = SocketItem( new icmp::socket(*io_serv, protocol) ); + NetworkInterface + NetInterface( network_interface, *Socket ); + + if ( !NetInterface.bind() ) + { + GlobalLogger.error() + << "Trouble creating IcmpPacketDistributor for interface " + << network_interface// << " and protocol " << protocol + << ": could not bind the socket with the local interface. " + << ::strerror( errno ) << std::endl; + } + + register_receive_handler(); +} + + +void IcmpPacketDistributor::register_receive_handler() +{ + // Waiting for a reply, We prepare the buffer to receive up to SOCKET_BUFFER_SIZE bytes + Socket->async_receive( + ReplyBuffer.prepare( SOCKET_BUFFER_SIZE ), + boost::bind( &IcmpPacketDistributor::handle_receive, this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred ) + ); +} + +void IcmpPacketDistributor::handle_receive( const boost::system::error_code &error, + const size_t &bytes_transferred ) +{ + if ( error ) + { + GlobalLogger.warning() + << ": Received error " << error + << " in ICMP packet distributor; end handler and schedule another."; + register_receive_handler(); + return; + } + + // The actual number of bytes received is committed to the buffer so that we + // can extract it using a std::istream object. + ReplyBuffer.commit( bytes_transferred ); + + GlobalLogger.info() << "received packet in distributor" << std::endl; + + try + { + std::istream is( &ReplyBuffer ); + if ( !is ) + { + GlobalLogger.error() << "Can't handle ReplyBuffer" << std::endl; + return; + } + + // Decode the reply packet. + IcmpPacketItem icmp_packet = IcmpPacketFactory::create_icmp_packet( Protocol, is ); + if ( !icmp_packet ) + { + GlobalLogger.warning() << "Ignoring broken ICMP packet" << std::endl; + } + + // check which pinger wants this packet + bool packet_matches = false; + BOOST_FOREACH( IcmpPingerItem pinger, PingerList ) + { + packet_matches |= pinger->handle_receive_icmp_packet(icmp_packet, bytes_received); + if (packet_matches) + break; + } + + if (!packet_matches) + GlobalLogger.warning() << "Packet did not match any pinger" << std::endl; + + catch ( ... ) + { + GlobalLogger.notice() << "Exception during ICMP parse." << std::endl; + } + + // re-register receive handler + register_receive_handler(); +} + +bool IcmpPacketDistributor::register_pinger( const IcmpPingerItem new_pinger ) +{ + std::pair result = PingerList.insert(new_pinger); + bool was_new = result.second; + if (was_new) + GlobalLogger.info() << "Register new pinger with IcmpPacketDistributor" << std::endl; + else + GlobalLogger.warning() << "Pinger to register was already known in IcmpPacketDistributor" + << std::endl; + return was_new; +} + + +bool IcmpPacketDistributor::unregister_pinger( const IcmpPingerItem old_pinger ) +{ + int n_erased = PingerList.erase(old_pinger); + bool was_erased = n_erased > 0; + if (was_erased) + GlobalLogger.info() << "Removed pinger from IcmpPacketDistributor" << std::endl; + else + GlobalLogger.warning() << "Could not find pinger to remove from IcmpPacketDistributor" + << std::endl; + return was_erased; +} + +/** + * @brief for all instances: close sockets, unregister all pingers + */ +void IcmpPacketDistributor::clean_up_all() +{ + BOOST_FOREACH( map_type::value_type &instance, Instances ) + instance.second->clean_up(); + + Instances.clear(); +} + +void IcmpPacketDistributor::clean_up() +{ + if (PingerList.size() > 0) + GlobalLogger.warning() << "There were still " << PingerList.size() + << " pingers registered in IcmpPacketDistributor!" << std::endl; + PingerList.clear(); + + boost::system::error_code error; + //Socket->shutdown(icmp::socket::shutdown_both, error); // both=send and receive + //if ( error ) + // GlobalLogger.warning() << "Received error " << error << " when shutting down ICMP socket"; + // always gave an error system:9 (probably EBADF: Bad file descriptor) + + Socket->close(error); + if ( error ) + GlobalLogger.warning() << "Received error " << error << " when closing ICMP socket"; +} + +IcmpPacketDistributor::~IcmpPacketDistributor() +{ + GlobalLogger.info() << "Destroying IcmpPacketDistributor" << std::endl; +} + +SocketItem IcmpPacketDistributor::get_socket() const +{ + return Socket; +} +// (created using vim -- the world's best text editor) + diff --git a/src/icmp/icmppacketdistributor.h b/src/icmp/icmppacketdistributor.h new file mode 100644 index 0000000..af475b2 --- /dev/null +++ b/src/icmp/icmppacketdistributor.h @@ -0,0 +1,119 @@ +/* + 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. + + Christian Herdtweck, Intra2net AG 2015 + */ + +#ifndef ICMP_PAKET_DISTRIBUTOR_H +#define ICMP_PAKET_DISTRIBUTOR_H + +#include +#include +#include +#include + +#include "host/pinger.h" +#include "host/networkinterface.hpp" +#include "icmp/icmppinger.h" + +using boost::asio::ip::icmp; + +// for each IP protocol (v4/v6) and each network interface (string), +// there can only be one IcmpPacketDistributor instance +typedef std::pair DistributorInstanceIdentifier; + +struct IcmpPacketDistributorInstanceIdentifierComparator +{ + bool operator() ( const DistributorInstanceIdentifier &a, + const DistributorInstanceIdentifier &b ) const ; +}; + +class IcmpPacketDistributor; + +typedef boost::shared_ptr IcmpPacketDistributorItem; +typedef std::map map_type; + +typedef boost::shared_ptr SocketItem; + +//----------------------------------------------------------------------------- +// IcmpPacketDistributor +//----------------------------------------------------------------------------- + +class IcmpPacketDistributor +{ +public: + bool register_pinger( const IcmpPingerItem &new_pinger ); + bool unregister_pinger( const IcmpPingerItem &old_pinger ); + + SocketItem get_socket() const; + + static IcmpPacketDistributorItem get_distributor( + const icmp::socket::protocol_type &protocol, + const std::string &network_interface, + const IoServiceItem io_serv + ); + + static IcmpPacketDistributorItem get_distributor( + const icmp::socket::protocol_type &protocol, + const std::string &network_interface + ); + + static void clean_up_all(); + + ~IcmpPacketDistributor(); + +private: + // hide away constructor, copy constructor and assignment operator + IcmpPacketDistributor( + const icmp::socket::protocol_type &protocol, + const std::string &network_interface, + const IoServiceItem io_serv + ); + IcmpPacketDistributor(IcmpPacketDistributor const&); + void operator=(IcmpPacketDistributor const&); + + void register_receive_handler(); + void handle_receive( const boost::system::error_code &error, + const size_t &bytes_transferred ); + void clean_up(); + + +private: + /// The socket object + SocketItem Socket; + + /// Network layer protocol used to ping, IPv4 or IPv6 + icmp::socket::protocol_type Protocol; + + /// The buffer where the data received will be placed + boost::asio::streambuf ReplyBuffer; + + std::set PingerList; + + /// Instances, one for each (protocol, interface) - pair + static map_type Instances; + +}; + + +#endif // ICMP_PAKET_DISTRIBUTOR_H + +// (created using vim -- the world's best text editor) + diff --git a/src/icmp/icmppaketdistributor.cpp b/src/icmp/icmppaketdistributor.cpp deleted file mode 100644 index bfa090d..0000000 --- a/src/icmp/icmppaketdistributor.cpp +++ /dev/null @@ -1,266 +0,0 @@ -/* - 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. - - Christian Herdtweck, Intra2net AG 2015 - */ - -#include "icmppaketdistributor.h" - -#include -#include -#include -#include -#include - -#include "boost_assert_handler.h" -#include "icmp/icmppacketfactory.h" - - -using I2n::Logger::GlobalLogger; -using boost::asio::ip::icmp; - -static const std::size_t SOCKET_BUFFER_SIZE = 65536; // 64kB - -typedef std::set::iterator PingerListIterator; - - -bool IcmpPacketDistributorInstanceIdentifierComparator::operator() ( - const DistributorInstanceIdentifier &a, - const DistributorInstanceIdentifier &b ) const -{ - if ( a.first == boost::asio::ip::icmp::v4() ) - { - if ( b.first == boost::asio::ip::icmp::v4() ) - return a.second < b.second; // v4 == v4 - else - BOOST_ASSERT( b.first == boost::asio::ip::icmp::v6() ); - return true; // a(v4) < b(b6) - } - else - { - BOOST_ASSERT( a.first == boost::asio::ip::icmp::v6() ); - - if ( b.first == boost::asio::ip::icmp::v4() ) - return false; // a(v6) > b(v4) - else - BOOST_ASSERT( b.first == boost::asio::ip::icmp::v6() ); - return a.second < b.second; // v6 == v6 - } -} - -//----------------------------------------------------------------------------- -// Definition of IcmpPacketDistributor -//----------------------------------------------------------------------------- - -map_type IcmpPacketDistributor::Instances; // initialize - - -IcmpPacketDistributorItem IcmpPacketDistributor::get_distributor( - const icmp::socket::protocol_type &protocol, - const std::string &network_interface, - const IoServiceItem io_serv ) -{ - DistributorInstanceIdentifier identifier(protocol, network_interface); - - // check if there is an instance for this protocol and interface - if ( Instances.count(identifier) == 0 ) - { // need to create an instance for this protocol and network interface - GlobalLogger.info() << "Creating IcmpPacketDistributor for interface " - << network_interface << std::endl; - IcmpPacketDistributorItem new_instance( new IcmpPacketDistributor( - protocol, network_interface, io_serv ) ); - Instances[identifier] = new_instance; - } - - BOOST_ASSERT( Instances.count(identifier) == 1 ); - - // return the one instance for this protocol and interface - return Instances[identifier]; -} - - -IcmpPacketDistributorItem IcmpPacketDistributor::get_distributor( - const icmp::socket::protocol_type &protocol, - const std::string &network_interface ) -{ - DistributorInstanceIdentifier identifier(protocol, network_interface); - - BOOST_ASSERT( Instances.count(identifier) == 1 ); - - // return the one instance for this protocol and interface - return Instances[identifier]; -} - - -IcmpPacketDistributor::IcmpPacketDistributor( - const icmp::socket::protocol_type &protocol, - const std::string &network_interface, - const IoServiceItem io_serv ): - Protocol( protocol ), - ReplyBuffer(), - PingerList() -{ - Socket = SocketItem( new icmp::socket(*io_serv, protocol) ); - NetworkInterface - NetInterface( network_interface, *Socket ); - - if ( !NetInterface.bind() ) - { - GlobalLogger.error() - << "Trouble creating IcmpPacketDistributor for interface " - << network_interface// << " and protocol " << protocol - << ": could not bind the socket with the local interface. " - << ::strerror( errno ) << std::endl; - } - - register_receive_handler(); -} - - -void IcmpPacketDistributor::register_receive_handler() -{ - // Waiting for a reply, We prepare the buffer to receive up to SOCKET_BUFFER_SIZE bytes - Socket->async_receive( - ReplyBuffer.prepare( SOCKET_BUFFER_SIZE ), - boost::bind( &IcmpPacketDistributor::handle_receive, this, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred ) - ); -} - -void IcmpPacketDistributor::handle_receive( const boost::system::error_code &error, - const size_t &bytes_transferred ) -{ - if ( error ) - { - GlobalLogger.warning() - << ": Received error " << error - << " in ICMP packet distributor; end handler and schedule another."; - register_receive_handler(); - return; - } - - // The actual number of bytes received is committed to the buffer so that we - // can extract it using a std::istream object. - ReplyBuffer.commit( bytes_transferred ); - - GlobalLogger.info() << "received packet in distributor" << std::endl; - - try - { - std::istream is( &ReplyBuffer ); - if ( !is ) - { - GlobalLogger.error() << "Can't handle ReplyBuffer" << std::endl; - return; - } - - // Decode the reply packet. - IcmpPacketItem icmp_packet = IcmpPacketFactory::create_icmp_packet( Protocol, is ); - if ( !icmp_packet ) - { - GlobalLogger.warning() << "Ignoring broken ICMP packet" << std::endl; - } - - // check which pinger wants this packet - bool packet_matches = false; - BOOST_FOREACH( IcmpPingerItem pinger, PingerList ) - { - packet_matches |= pinger->handle_receive_icmp_packet(icmp_packet, bytes_received); - if (packet_matches) - break; - } - - if (!packet_matches) - GlobalLogger.warning() << "Packet did not match any pinger" << std::endl; - - catch ( ... ) - { - GlobalLogger.notice() << "Exception during ICMP parse." << std::endl; - } - - // re-register receive handler - register_receive_handler(); -} - -bool IcmpPacketDistributor::register_pinger( const IcmpPingerItem new_pinger ) -{ - std::pair result = PingerList.insert(new_pinger); - bool was_new = result.second; - if (was_new) - GlobalLogger.info() << "Register new pinger with IcmpPacketDistributor" << std::endl; - else - GlobalLogger.warning() << "Pinger to register was already known in IcmpPacketDistributor" - << std::endl; - return was_new; -} - - -bool IcmpPacketDistributor::unregister_pinger( const IcmpPingerItem old_pinger ) -{ - int n_erased = PingerList.erase(old_pinger); - bool was_erased = n_erased > 0; - if (was_erased) - GlobalLogger.info() << "Removed pinger from IcmpPacketDistributor" << std::endl; - else - GlobalLogger.warning() << "Could not find pinger to remove from IcmpPacketDistributor" - << std::endl; - return was_erased; -} - -/** - * @brief for all instances: close sockets, unregister all pingers - */ -void IcmpPacketDistributor::clean_up_all() -{ - BOOST_FOREACH( map_type::value_type &instance, Instances ) - instance.second->clean_up(); - - Instances.clear(); -} - -void IcmpPacketDistributor::clean_up() -{ - if (PingerList.size() > 0) - GlobalLogger.warning() << "There were still " << PingerList.size() - << " pingers registered in IcmpPacketDistributor!" << std::endl; - PingerList.clear(); - - boost::system::error_code error; - //Socket->shutdown(icmp::socket::shutdown_both, error); // both=send and receive - //if ( error ) - // GlobalLogger.warning() << "Received error " << error << " when shutting down ICMP socket"; - // always gave an error system:9 (probably EBADF: Bad file descriptor) - - Socket->close(error); - if ( error ) - GlobalLogger.warning() << "Received error " << error << " when closing ICMP socket"; -} - -IcmpPacketDistributor::~IcmpPacketDistributor() -{ - GlobalLogger.info() << "Destroying IcmpPacketDistributor" << std::endl; -} - -SocketItem IcmpPacketDistributor::get_socket() const -{ - return Socket; -} -// (created using vim -- the world's best text editor) - diff --git a/src/icmp/icmppaketdistributor.h b/src/icmp/icmppaketdistributor.h deleted file mode 100644 index af475b2..0000000 --- a/src/icmp/icmppaketdistributor.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - 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. - - Christian Herdtweck, Intra2net AG 2015 - */ - -#ifndef ICMP_PAKET_DISTRIBUTOR_H -#define ICMP_PAKET_DISTRIBUTOR_H - -#include -#include -#include -#include - -#include "host/pinger.h" -#include "host/networkinterface.hpp" -#include "icmp/icmppinger.h" - -using boost::asio::ip::icmp; - -// for each IP protocol (v4/v6) and each network interface (string), -// there can only be one IcmpPacketDistributor instance -typedef std::pair DistributorInstanceIdentifier; - -struct IcmpPacketDistributorInstanceIdentifierComparator -{ - bool operator() ( const DistributorInstanceIdentifier &a, - const DistributorInstanceIdentifier &b ) const ; -}; - -class IcmpPacketDistributor; - -typedef boost::shared_ptr IcmpPacketDistributorItem; -typedef std::map map_type; - -typedef boost::shared_ptr SocketItem; - -//----------------------------------------------------------------------------- -// IcmpPacketDistributor -//----------------------------------------------------------------------------- - -class IcmpPacketDistributor -{ -public: - bool register_pinger( const IcmpPingerItem &new_pinger ); - bool unregister_pinger( const IcmpPingerItem &old_pinger ); - - SocketItem get_socket() const; - - static IcmpPacketDistributorItem get_distributor( - const icmp::socket::protocol_type &protocol, - const std::string &network_interface, - const IoServiceItem io_serv - ); - - static IcmpPacketDistributorItem get_distributor( - const icmp::socket::protocol_type &protocol, - const std::string &network_interface - ); - - static void clean_up_all(); - - ~IcmpPacketDistributor(); - -private: - // hide away constructor, copy constructor and assignment operator - IcmpPacketDistributor( - const icmp::socket::protocol_type &protocol, - const std::string &network_interface, - const IoServiceItem io_serv - ); - IcmpPacketDistributor(IcmpPacketDistributor const&); - void operator=(IcmpPacketDistributor const&); - - void register_receive_handler(); - void handle_receive( const boost::system::error_code &error, - const size_t &bytes_transferred ); - void clean_up(); - - -private: - /// The socket object - SocketItem Socket; - - /// Network layer protocol used to ping, IPv4 or IPv6 - icmp::socket::protocol_type Protocol; - - /// The buffer where the data received will be placed - boost::asio::streambuf ReplyBuffer; - - std::set PingerList; - - /// Instances, one for each (protocol, interface) - pair - static map_type Instances; - -}; - - -#endif // ICMP_PAKET_DISTRIBUTOR_H - -// (created using vim -- the world's best text editor) - -- 1.7.1