From 41d175b00eb0427ccd4c20d808e9291a81b16165 Mon Sep 17 00:00:00 2001 From: Christian Herdtweck Date: Thu, 5 Feb 2015 17:17:54 +0100 Subject: [PATCH] give up trying to define IcmpPacketDistributor in own files, just use icmppinger.h / .cpp for it The two classes depend on each other, so none compiles without the other if they are defined in separate files. In the same file, the compiler manages. --- src/icmp/icmppacketdistributor.cpp | 282 ------------------------------------ src/icmp/icmppacketdistributor.h | 117 --------------- src/icmp/icmppinger.cpp | 5 +- src/icmp/icmppinger.h | 1 - src/main.cpp | 3 +- 5 files changed, 3 insertions(+), 405 deletions(-) delete mode 100644 src/icmp/icmppacketdistributor.cpp delete mode 100644 src/icmp/icmppacketdistributor.h diff --git a/src/icmp/icmppacketdistributor.cpp b/src/icmp/icmppacketdistributor.cpp deleted file mode 100644 index f406a56..0000000 --- a/src/icmp/icmppacketdistributor.cpp +++ /dev/null @@ -1,282 +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 "icmppacketdistributor.h" - -#include -#include -#include -#include -#include - -#include "boost_assert_handler.h" -#include "host/networkinterface.hpp" -#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 IcmpPacketDistributor::InstanceIdentifierComparator::operator() ( - const IcmpPacketDistributor::DistributorInstanceIdentifier &a, - const IcmpPacketDistributor::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 -//----------------------------------------------------------------------------- - -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 ) -{ - IcmpPacketDistributor::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 ) -{ - IcmpPacketDistributor::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() -{ - // wait for reply, prepare 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_transferred); - 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( IcmpPacketDistributor::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&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 deleted file mode 100644 index 9ea8c27..0000000 --- a/src/icmp/icmppacketdistributor.h +++ /dev/null @@ -1,117 +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_PACKET_DISTRIBUTOR_H -#define ICMP_PACKET_DISTRIBUTOR_H - -#include -#include -#include -#include - -#include "icmp/icmppinger.h" - -using boost::asio::ip::icmp; - -typedef boost::shared_ptr IoServiceItem; -typedef boost::shared_ptr SocketItem; - -//----------------------------------------------------------------------------- -// IcmpPacketDistributor -//----------------------------------------------------------------------------- - -class IcmpPacketDistributor; -typedef boost::shared_ptr IcmpPacketDistributorItem; - -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; - - // for each IP protocol (v4/v6) and each network interface (string), - // there can only be one IcmpPacketDistributor instance - typedef std::pair - DistributorInstanceIdentifier; - - struct InstanceIdentifierComparator - { - bool operator() ( const DistributorInstanceIdentifier &a, - const DistributorInstanceIdentifier &b ) const ; - }; - - typedef std::map map_type; - /// Instances, one for each (protocol, interface) - pair - static map_type Instances; - -}; - -#endif // ICMP_PACKET_DISTRIBUTOR_H - -// (created using vim -- the world's best text editor) - diff --git a/src/icmp/icmppinger.cpp b/src/icmp/icmppinger.cpp index d059240..3c50cfe 100644 --- a/src/icmp/icmppinger.cpp +++ b/src/icmp/icmppinger.cpp @@ -15,14 +15,13 @@ #include #include #include -#include // DEBUG: distributor in pinger +#include #include #include "boost_assert_handler.h" #include "icmp/icmppacketfactory.h" -//#include "icmp/icmppacketdistributor.h" // DEBUG: distributor in pinger -#include "host/networkinterface.hpp" // DEBUG: distributor in pinger +#include "host/networkinterface.hpp" using namespace std; using boost::asio::const_buffers_1; diff --git a/src/icmp/icmppinger.h b/src/icmp/icmppinger.h index 5f0a512..ee20c50 100644 --- a/src/icmp/icmppinger.h +++ b/src/icmp/icmppinger.h @@ -20,7 +20,6 @@ #include "host/pinger.h" #include "host/pingstatus.h" #include "icmp/icmppacket.h" -//#include "icmp/icmppacketdistributor.h" DEBUG: distributor in pinger using boost::asio::ip::icmp; diff --git a/src/main.cpp b/src/main.cpp index e659e63..003622b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -41,8 +41,7 @@ on this file might be covered by the GNU General Public License. #include "host/pingerfactory.h" #include "host/pingprotocol.h" #include "host/pingscheduler.h" -//#include "icmp/icmppacketdistributor.h" DEBUG: distributor in pinger -#include "icmp/icmppinger.h" // DEBUG: distributor in pinger +#include "icmp/icmppinger.h" // contains IcmpPacketDistributor using namespace std; -- 1.7.1