start removing socket use from IcmpPinger to only have IcmpPacketDistributor deal...
authorChristian Herdtweck <christian.herdtweck@intra2net.com>
Mon, 26 Jan 2015 16:32:01 +0000 (17:32 +0100)
committerChristian Herdtweck <christian.herdtweck@intra2net.com>
Mon, 26 Jan 2015 16:32:01 +0000 (17:32 +0100)
src/host/pinger.h
src/host/pingerfactory.cpp
src/icmp/icmppaketdistributor.cpp
src/icmp/icmppaketdistributor.h
src/icmp/icmppinger.cpp
src/icmp/icmppinger.h
src/main.cpp

index 705e40e..72a4839 100644 (file)
@@ -66,7 +66,7 @@ protected:
     virtual ~Pinger();
 
     Pinger::WeakPtr get_myself() const;
-    void set_myself(const Pinger::WeakPtr &myself);
+    virtual void set_myself(const Pinger::WeakPtr &myself);
 
 private:
     Pinger::WeakPtr Myself;
index 17285a2..e14ff5c 100644 (file)
@@ -30,7 +30,6 @@
 #include <logfunc.hpp>
 
 #include "boost_assert_handler.h"
-#include "icmp/icmppaketdistributor.h"
 #include "icmp/icmppinger.h"
 #include "tcp/tcppinger.h"
 
index 1772b32..bfa090d 100644 (file)
 
 #include "icmppaketdistributor.h"
 
+#include <istream>
 #include <errno.h>
 #include <logfunc.hpp>
 #include <boost/bind.hpp>
 #include <boost/foreach.hpp>
 
 #include "boost_assert_handler.h"
+#include "icmp/icmppacketfactory.h"
 
 
 using I2n::Logger::GlobalLogger;
@@ -35,10 +37,10 @@ using boost::asio::ip::icmp;
 
 static const std::size_t SOCKET_BUFFER_SIZE = 65536;   // 64kB
 
-typedef std::set<PingerItem>::iterator PingerListIterator;
+typedef std::set<IcmpPingerItem>::iterator PingerListIterator;
 
 
-bool IcmpPaketDistributorInstanceIdentifierComparator::operator() (
+bool IcmpPacketDistributorInstanceIdentifierComparator::operator() (
                                 const DistributorInstanceIdentifier &a,
                                 const DistributorInstanceIdentifier &b ) const
 {
@@ -63,13 +65,13 @@ bool IcmpPaketDistributorInstanceIdentifierComparator::operator() (
 }
 
 //-----------------------------------------------------------------------------
-// Definition of IcmpPaketDistributor
+// Definition of IcmpPacketDistributor
 //-----------------------------------------------------------------------------
 
-map_type IcmpPaketDistributor::Instances;   // initialize
+map_type IcmpPacketDistributor::Instances;   // initialize
 
 
-IcmpPaketDistributorItem IcmpPaketDistributor::get_distributor(
+IcmpPacketDistributorItem IcmpPacketDistributor::get_distributor(
         const icmp::socket::protocol_type &protocol,
         const std::string &network_interface,
         const IoServiceItem io_serv )
@@ -79,9 +81,9 @@ IcmpPaketDistributorItem IcmpPaketDistributor::get_distributor(
     // 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 IcmpPaketDistributor for interface "
+        GlobalLogger.info() << "Creating IcmpPacketDistributor for interface "
                             << network_interface << std::endl;
-        IcmpPaketDistributorItem new_instance( new IcmpPaketDistributor(
+        IcmpPacketDistributorItem new_instance( new IcmpPacketDistributor(
                     protocol, network_interface, io_serv ) );
         Instances[identifier] = new_instance;
     }
@@ -93,7 +95,7 @@ IcmpPaketDistributorItem IcmpPaketDistributor::get_distributor(
 }
 
 
-IcmpPaketDistributorItem IcmpPaketDistributor::get_distributor(
+IcmpPacketDistributorItem IcmpPacketDistributor::get_distributor(
         const icmp::socket::protocol_type &protocol,
         const std::string &network_interface )
 {
@@ -106,22 +108,22 @@ IcmpPaketDistributorItem IcmpPaketDistributor::get_distributor(
 }
 
 
-IcmpPaketDistributor::IcmpPaketDistributor(
+IcmpPacketDistributor::IcmpPacketDistributor(
             const icmp::socket::protocol_type &protocol,
             const std::string &network_interface,
             const IoServiceItem io_serv ):
-    Socket( *io_serv, protocol ),
     Protocol( protocol ),
     ReplyBuffer(),
     PingerList()
 {
+    Socket = SocketItem( new icmp::socket(*io_serv, protocol) );
     NetworkInterface<icmp::socket, boost::asio::ip::icmp>
-                  NetInterface( network_interface, Socket );
+                  NetInterface( network_interface, *Socket );
 
     if ( !NetInterface.bind() )
     {
         GlobalLogger.error()
-           << "Trouble creating IcmpPaketDistributor for interface "
+           << "Trouble creating IcmpPacketDistributor for interface "
            << network_interface// << " and protocol " << protocol
            << ": could not bind the socket with the local interface. "
            << ::strerror( errno )  << std::endl;
@@ -131,18 +133,18 @@ IcmpPaketDistributor::IcmpPaketDistributor(
 }
 
 
-void IcmpPaketDistributor::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(
+    Socket->async_receive(
             ReplyBuffer.prepare( SOCKET_BUFFER_SIZE ),
-            boost::bind( &IcmpPaketDistributor::handle_receive, this,
+            boost::bind( &IcmpPacketDistributor::handle_receive, this,
                          boost::asio::placeholders::error,
                          boost::asio::placeholders::bytes_transferred )
     );
 }
 
-void IcmpPaketDistributor::handle_receive( const boost::system::error_code &error,
+void IcmpPacketDistributor::handle_receive( const boost::system::error_code &error,
                                            const size_t &bytes_transferred )
 {
     if ( error )
@@ -158,32 +160,66 @@ void IcmpPaketDistributor::handle_receive( const boost::system::error_code &erro
     // can extract it using a std::istream object.
     ReplyBuffer.commit( bytes_transferred );
 
-    GlobalLogger.info() << "received paket in distributor" << std::endl;
+    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 IcmpPaketDistributor::register_pinger( const PingerItem new_pinger )
+bool IcmpPacketDistributor::register_pinger( const IcmpPingerItem new_pinger )
 {
     std::pair<PingerListIterator, bool> result = PingerList.insert(new_pinger);
     bool was_new = result.second;
     if (was_new)
-        GlobalLogger.info() << "Register new pinger with IcmpPaketDistributor" << std::endl;
+        GlobalLogger.info() << "Register new pinger with IcmpPacketDistributor" << std::endl;
     else
-        GlobalLogger.warning() << "Pinger to register was already known in IcmpPaketDistributor"
+        GlobalLogger.warning() << "Pinger to register was already known in IcmpPacketDistributor"
                                << std::endl;
     return was_new;
 }
 
 
-bool IcmpPaketDistributor::unregister_pinger( const PingerItem old_pinger )
+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 IcmpPaketDistributor" << std::endl;
+        GlobalLogger.info() << "Removed pinger from IcmpPacketDistributor" << std::endl;
     else
-        GlobalLogger.warning() << "Could not find pinger to remove from IcmpPaketDistributor"
+        GlobalLogger.warning() << "Could not find pinger to remove from IcmpPacketDistributor"
                                << std::endl;
     return was_erased;
 }
@@ -191,7 +227,7 @@ bool IcmpPaketDistributor::unregister_pinger( const PingerItem old_pinger )
 /**
  * @brief for all instances: close sockets, unregister all pingers
  */
-void IcmpPaketDistributor::clean_up_all()
+void IcmpPacketDistributor::clean_up_all()
 {
     BOOST_FOREACH( map_type::value_type &instance, Instances )
         instance.second->clean_up();
@@ -199,28 +235,32 @@ void IcmpPaketDistributor::clean_up_all()
     Instances.clear();
 }
 
-void IcmpPaketDistributor::clean_up()
+void IcmpPacketDistributor::clean_up()
 {
     if (PingerList.size() > 0)
         GlobalLogger.warning() << "There were still " << PingerList.size()
-            << " pingers registered in IcmpPaketDistributor!" << std::endl;
+            << " pingers registered in IcmpPacketDistributor!" << std::endl;
     PingerList.clear();
 
     boost::system::error_code error;
-    //Socket.shutdown(icmp::socket::shutdown_both, error);    // both=send and receive
+    //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);
+    Socket->close(error);
     if ( error )
         GlobalLogger.warning() << "Received error " << error << " when closing ICMP socket";
 }
 
-IcmpPaketDistributor::~IcmpPaketDistributor()
+IcmpPacketDistributor::~IcmpPacketDistributor()
 {
-    GlobalLogger.info() << "Destroying IcmpPaketDistributor" << std::endl;
+    GlobalLogger.info() << "Destroying IcmpPacketDistributor" << std::endl;
 }
 
+SocketItem IcmpPacketDistributor::get_socket() const
+{
+    return Socket;
+}
 // (created using vim -- the world's best text editor)
 
index fbcf711..af475b2 100644 (file)
 using boost::asio::ip::icmp;
 
 // for each IP protocol (v4/v6) and each network interface (string),
-//   there can only be one IcmpPaketDistributor instance
+//   there can only be one IcmpPacketDistributor instance
 typedef std::pair<icmp::socket::protocol_type, std::string> DistributorInstanceIdentifier;
 
-struct IcmpPaketDistributorInstanceIdentifierComparator
+struct IcmpPacketDistributorInstanceIdentifierComparator
 {
     bool operator() ( const DistributorInstanceIdentifier &a,
                       const DistributorInstanceIdentifier &b ) const ;
 };
 
-class IcmpPaketDistributor;
+class IcmpPacketDistributor;
 
-typedef boost::shared_ptr<IcmpPaketDistributor> IcmpPaketDistributorItem;
-typedef std::map<DistributorInstanceIdentifier, IcmpPaketDistributorItem,
-                 IcmpPaketDistributorInstanceIdentifierComparator> map_type;
+typedef boost::shared_ptr<IcmpPacketDistributor> IcmpPacketDistributorItem;
+typedef std::map<DistributorInstanceIdentifier, IcmpPacketDistributorItem,
+                 IcmpPacketDistributorInstanceIdentifierComparator> map_type;
+
+typedef boost::shared_ptr<icmp::socket> SocketItem;
 
 //-----------------------------------------------------------------------------
-// IcmpPaketDistributor
+// IcmpPacketDistributor
 //-----------------------------------------------------------------------------
 
-class IcmpPaketDistributor
+class IcmpPacketDistributor
 {
 public:
-    bool register_pinger( const PingerItem new_pinger );
-    bool unregister_pinger( const PingerItem old_pinger );
+    bool register_pinger( const IcmpPingerItem &new_pinger );
+    bool unregister_pinger( const IcmpPingerItem &old_pinger );
+
+    SocketItem get_socket() const;
 
-    static IcmpPaketDistributorItem get_distributor(
+    static IcmpPacketDistributorItem get_distributor(
             const icmp::socket::protocol_type &protocol,
             const std::string &network_interface,
-            const IoServiceItem io_serv );
+            const IoServiceItem io_serv
+    );
 
-    static IcmpPaketDistributorItem get_distributor(
+    static IcmpPacketDistributorItem get_distributor(
             const icmp::socket::protocol_type &protocol,
-            const std::string &network_interface );
+            const std::string &network_interface
+    );
 
     static void clean_up_all();
 
-    ~IcmpPaketDistributor();
+    ~IcmpPacketDistributor();
 
 private:
-    // hide away constructor, copy constructor and copy operator
-    IcmpPaketDistributor(
+    // hide away constructor, copy constructor and assignment operator
+    IcmpPacketDistributor(
             const icmp::socket::protocol_type &protocol,
             const std::string &network_interface,
-            const IoServiceItem io_serv );
-    IcmpPaketDistributor(IcmpPaketDistributor const&);
-    void operator=(IcmpPaketDistributor const&);
+            const IoServiceItem io_serv
+    );
+    IcmpPacketDistributor(IcmpPacketDistributor const&);
+    void operator=(IcmpPacketDistributor const&);
 
     void register_receive_handler();
     void handle_receive( const boost::system::error_code &error,
@@ -90,7 +97,7 @@ private:
 
 private:
     /// The socket object
-    icmp::socket Socket;
+    SocketItem Socket;
 
     /// Network layer protocol used to ping, IPv4 or IPv6
     icmp::socket::protocol_type Protocol;
@@ -98,7 +105,7 @@ private:
     /// The buffer where the data received will be placed
     boost::asio::streambuf ReplyBuffer;
 
-    std::set<PingerItem> PingerList;
+    std::set<IcmpPingerItem> PingerList;
 
     /// Instances, one for each (protocol, interface) - pair
     static map_type Instances;
index 8a43eed..af2b8d7 100644 (file)
@@ -7,9 +7,7 @@
 #include "icmp/icmppinger.h"
 
 #include <errno.h>
-#include <sys/socket.h>
 
-#include <istream>
 #include <ostream>
 
 #include <boost/bind.hpp>
@@ -22,7 +20,6 @@
 
 #include "boost_assert_handler.h"
 #include "icmp/icmppacketfactory.h"
-#include "icmp/icmppaketdistributor.h"
 
 using namespace std;
 using boost::asio::const_buffers_1;
@@ -39,8 +36,36 @@ using I2n::Logger::GlobalLogger;
 // IcmpPinger
 //-----------------------------------------------------------------------------
 
-/// size of buffer used to read from socket in [bytes]
-static const std::size_t SOCKET_BUFFER_SIZE = 65536;   // 64kB
+/**
+ * @brief factory function for IcmpPingers, ensures that set_myself is set
+ *
+ * @returns a shared pointer to a Pinger
+ */
+PingerItem IcmpPinger::create(
+        const IoServiceItem io_serv,
+        const icmp::socket::protocol_type &protocol,
+        const string &source_network_interface,
+        const int echo_reply_timeout_in_sec )
+{
+    // get distributor
+    IcmpPacketDistributorItem distributor = IcmpPacketDistributor::get_distributor(
+            icmp::v4(), source_network_interface, io_serv);
+
+    // create pinger
+    IcmpPinger *ptr = new IcmpPinger(io_serv, protocol, echo_reply_timeout_in_sec);
+    IcmpPingerItem shared_ptr_(ptr);
+    Pinger::WeakPtr weak_ptr( shared_ptr_ );
+
+    // keep weak pointer to self
+    //shared_ptr_->set_myself( weak_ptr ); //Error: Pinger::set_myself is protected
+    ptr->set_myself( weak_ptr );
+
+    // register in distributor
+    distributor->register_pinger(shared_ptr_);
+
+    // done, return shared ptr
+    return shared_ptr_;
+}
 
 /**
  * @brief Parameterized constructor.
@@ -54,32 +79,19 @@ static const std::size_t SOCKET_BUFFER_SIZE = 65536;   // 64kB
 IcmpPinger::IcmpPinger(
         const IoServiceItem io_serv,
         const icmp::socket::protocol_type &protocol,
-        const string &source_network_interface,
         const int echo_reply_timeout_in_sec
 ) :
     DestinationEndpoint(),
     Protocol( protocol ),
-    Socket( *io_serv, Protocol ),
-    NetInterface( source_network_interface, Socket ),
     IcmpPacketReceiveTimer( *io_serv ),
     Identifier( 0 ),
     SequenceNumber( 0 ),
     TimeSent( microsec_clock::universal_time() ),
-    ReplyBuffer(),
     ReplyReceived( false ),
     EchoReplyTimeoutInSec( echo_reply_timeout_in_sec ),
     PingerStatus( PingStatus_NotSent ),
-    PingDoneCallback(),
-    ReceiveHandlerInPlace( false )
+    PingDoneCallback()
 {
-    if ( !NetInterface.bind() )
-    {
-        GlobalLogger.error()
-           << DestinationEndpoint.address().to_string()
-           << ": could not bind the socket with the local interface. "
-           << ::strerror( errno )  << endl;
-    }
-
     // Create "unique" identifier
     boost::uuids::random_generator random_gen;
     boost::uuids::uuid random_tag = random_gen();
@@ -119,19 +131,13 @@ void IcmpPinger::ping(
 
     set_destination_endpoint( destination_ip );
 
-    if (start_send())
-        start_receive();
-    else
-        GlobalLogger.info()
-           << DestinationEndpoint.address().to_string()
-           << ": not scheduling receive since send failed." << endl;
-        // there might still be an old handler in place... cancel?
+    start_send();
 }
 
 void IcmpPinger::stop_pinging()
 {
-    IcmpPaketDistributor::get_distributor(Protocol, NetInterface.get_name())
-        ->unregister_pinger( get_myself().lock() );
+    IcmpPingerItem icmp_item = boost::const_pointer_cast<IcmpPinger>( get_myself().lock() );
+    PacketDistributor->unregister_pinger( icmp_item );
 }
 
 
@@ -180,7 +186,7 @@ bool IcmpPinger::send_echo_request( const IcmpPacketItem icmp_packet )
                     << ": sending ping" << endl;
         const_buffers_1 data = request_buffer.data();
         // Block until send the data
-        bytes_sent = Socket.send_to( data, DestinationEndpoint );
+        bytes_sent = PacketDistributor->get_socket()->send_to( data, DestinationEndpoint );
         if ( bytes_sent != buffer_size( data ) )
         {
             GlobalLogger.error()
@@ -250,168 +256,72 @@ void IcmpPinger::handle_timeout(const boost::system::error_code& error)
     PingDoneCallback( ping_success );
 }
 
-void IcmpPinger::start_receive()
-{
-    if ( ReceiveHandlerInPlace )
-    {
-        GlobalLogger.info()
-                   << DestinationEndpoint.address().to_string()
-                   << ": Receive Handler in place, do not schedule another one" << endl;
-        return;
-    }
-
-    // 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( &IcmpPinger::handle_receive_icmp_packet, this, boost::asio::placeholders::error,
-                                                                        boost::asio::placeholders::bytes_transferred )
-    );
-    ReceiveHandlerInPlace = true;
-}
 
 /**
  * @brief Receive ICMP packets
- * Note: Will receive -all- ICMP packets from the kernel. So if the packet doesn't match
- * our criteria, we have to schedule another start_receive() requests. The timeout stays the same.
- *
- * In the future we might redesign the code to handle all ICMP packets
- * from a single raw socket.
- *
  * @param bytes_transferred Number of bytes transferred.
- * @return void
+ * @return true if packet matches a request from this pinger, false otherwise
  **/
-void IcmpPinger::handle_receive_icmp_packet( const boost::system::error_code &error,
-                                             const size_t &bytes_transferred )
+bool IcmpPinger::handle_receive_icmp_packet(const IcmpPacketItem icmp_packet,
+                                            const size_t bytes_transferred )
 {
-
-    ReceiveHandlerInPlace = false;
-
-    if ( error )
-    {
-        GlobalLogger.warning()
-           << DestinationEndpoint.address().to_string()
-           << ": Received error " << error
-           << " in ICMP packet handler; end handler and schedule another.";
-        start_receive();
-        return;
-    }
     if ( ReplyReceived )
+        // continue, might be an old packet
+        // or return false right away, do not want packet anyway...
+        return false;
+
+    // We can receive all ICMP packets received by the host, so we need to
+    // filter out only the echo replies that match our identifier,
+    // expected sequence number, and destination host address (receive just
+    // the ICMP packets from the host we had ping).
+
+    bool does_match = false;
+    if ( icmp_packet->match_echo_reply(
+                            Identifier, SequenceNumber,
+                            DestinationEndpoint.address() ) )
     {
         GlobalLogger.info()
-            << DestinationEndpoint.address().to_string()
-            << ": Got another call to handler, probably due to earlier timeout. "
-            << "Ignore it." << endl;
-        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 );
-
-    try
-    {
-        istream is( &ReplyBuffer );
-        if ( !is )
-        {
-            GlobalLogger.error()
-               << DestinationEndpoint.address().to_string()
-               << ": Can't handle ReplyBuffer" << endl;
-            return;
-        }
-
-        // Decode the reply packet.
-        IcmpPacketItem icmp_packet = IcmpPacketFactory::create_icmp_packet( Protocol, is );
-        if ( !icmp_packet )
-        {
-            GlobalLogger.warning()
-               << DestinationEndpoint.address().to_string()
-               << ": Ignoring broken ICMP packet" << endl;
-            return;
-        }
-
-        // We can receive all ICMP packets received by the host, so we need to
-        // filter out only the echo replies that match the our identifier,
-        // expected sequence number, and destination host address (receive just
-        // the ICMP packets from the host we had ping).
-
-        if ( icmp_packet->match_echo_reply(
-                                Identifier, SequenceNumber,
-                                DestinationEndpoint.address() ) )
-        {
-            GlobalLogger.info()
-               << DestinationEndpoint.address().to_string()
-               << ": Received reply" << endl;
+           << DestinationEndpoint.address().to_string()
+           << ": Received reply" << endl;
 
-            ReplyReceived = true;
+        ReplyReceived = true;
+        does_match = true;
 
-            icmp_packet->print_echo_reply( bytes_transferred, TimeSent );
+        icmp_packet->print_echo_reply( bytes_transferred, TimeSent );
 
-            set_ping_status( PingStatus_SuccessReply );
+        set_ping_status( PingStatus_SuccessReply );
 
-            IcmpPacketReceiveTimer.cancel();                                        //lint !e534
-        }
-        else if ( icmp_packet->match_destination_unreachable(
-                                     Identifier, SequenceNumber,
-                                     DestinationEndpoint.address() ) )
-        {
-            GlobalLogger.info()
-               << DestinationEndpoint.address().to_string()
-               << ": Received destination unreachable" << endl;
+        IcmpPacketReceiveTimer.cancel();                                        //lint !e534
+    }
+    else if ( icmp_packet->match_destination_unreachable(
+                                 Identifier, SequenceNumber,
+                                 DestinationEndpoint.address() ) )
+    {
+        GlobalLogger.info()
+           << DestinationEndpoint.address().to_string()
+           << ": Received destination unreachable" << endl;
 
-            ReplyReceived = true;
+        ReplyReceived = true;
+        does_match = true;
 
-            icmp_packet->print_destination_unreachable();
+        icmp_packet->print_destination_unreachable();
 
-            set_ping_status( PingStatus_FailureDestinationUnreachable );
+        set_ping_status( PingStatus_FailureDestinationUnreachable );
 
-            IcmpPacketReceiveTimer.cancel();                                        //lint !e534
-        }
-        // Unknown ICMP reply, start another receive till timeout
-        else
-        {
-            GlobalLogger.info()
-               << DestinationEndpoint.address().to_string()
-               << ": Received packet that does not match" << endl;
-            start_receive();
-        }
+        IcmpPacketReceiveTimer.cancel();                                        //lint !e534
     }
-    catch ( ... )
+    // Unknown ICMP reply, start another receive till timeout
+    else
     {
-        GlobalLogger.notice()
+        GlobalLogger.info()
            << DestinationEndpoint.address().to_string()
-           << ": exception during ICMP parse. "
-            << "Starting another receive till timeout." << endl;
-        start_receive();
+           << ": Received packet that does not match" << endl;
     }
+
+    return does_match;
 }
 
 void IcmpPinger::set_ping_status( PingStatus ping_status )
 {
     PingerStatus = ping_status;
 }
-
-
-PingerItem IcmpPinger::create(
-        const IoServiceItem io_serv,
-        const icmp::socket::protocol_type &protocol,
-        const string &source_network_interface,
-        const int echo_reply_timeout_in_sec )
-{
-    // create pinger
-    IcmpPinger *ptr = new IcmpPinger(io_serv, protocol, source_network_interface,
-                                           echo_reply_timeout_in_sec);
-    PingerItem shared_ptr(ptr);
-    Pinger::WeakPtr weak_ptr( shared_ptr );
-
-    // keep weak pointer to self
-    ptr->set_myself( weak_ptr );
-    // shared_ptr->set_myself( weak_ptr ); Error: Pinger::set_myself is protected
-
-    // register in distributor
-    IcmpPaketDistributor::get_distributor(icmp::v4(), source_network_interface, io_serv)
-                          ->register_pinger(shared_ptr);
-
-    // done, return shared ptr
-    return shared_ptr;
-}
-
index 1ad9b63..d9b0026 100644 (file)
 
 #include <boost/asio.hpp>
 #include <boost/function.hpp>
+#include <boost/shared_ptr.hpp>
 
-#include "host/networkinterface.hpp"
 #include "host/pinger.h"
 #include "host/pingstatus.h"
 #include "icmp/icmppacket.h"
+#include "icmp/icmppaketdistributor.h"
+
+class IcmpPinger;
+typedef boost::shared_ptr<IcmpPinger> IcmpPingerItem;
 
 //-----------------------------------------------------------------------------
 // IcmpPinger
@@ -52,7 +56,6 @@ private:
     IcmpPinger(
             const IoServiceItem io_serv,
             const boost::asio::ip::icmp::socket::protocol_type &protocol,
-            const std::string &source_network_interface,
             const int echo_reply_timeout_in_sec
     );
 
@@ -63,21 +66,19 @@ private:
     void schedule_timeout_echo_reply();
     void handle_timeout(const boost::system::error_code &error);
 
-    void start_receive();
-    void handle_receive_icmp_packet( const boost::system::error_code &error,
-                                     const std::size_t &bytes_transferred );
+    bool handle_receive_icmp_packet(const IcmpPacketItem icmp_packet,
+                                    const size_t bytes_transferred
+    );
 
     void set_ping_status( PingStatus ping_status );
 
 private:
+    IcmpPacketDistributorItem PacketDistributor;
+
     /// The destination host
     boost::asio::ip::icmp::endpoint DestinationEndpoint;
     /// Network layer protocol used to ping, IPv4 or IPv6
     boost::asio::ip::icmp::socket::protocol_type Protocol;
-    /// The socket object
-    boost::asio::ip::icmp::socket Socket;
-    /// This object represents the network interface
-    NetworkInterface<boost::asio::ip::icmp::socket, boost::asio::ip::icmp> NetInterface;
     /// The timer of ICMP packet receive, triggers the timeout to avoid infinite
     /// wait
     boost::asio::deadline_timer IcmpPacketReceiveTimer;
@@ -87,8 +88,6 @@ private:
     uint16_t SequenceNumber;
     /// The time when the last ICMP packet was sent
     boost::posix_time::ptime TimeSent;
-    /// The buffer where the data received will be placed
-    boost::asio::streambuf ReplyBuffer;
     /// Flag to indicate if we got a reply or not
     bool ReplyReceived;
     /// The amount of time to wait for the reply
@@ -97,10 +96,6 @@ private:
     PingStatus PingerStatus;
     /// Callback to notify when the ping is done (got reply/timeout)
     boost::function< void(bool) > PingDoneCallback;
-    /// flag that have registered a handler, so do not accumulate handlers with timeouts
-    bool ReceiveHandlerInPlace;
 };
 
-typedef boost::shared_ptr<IcmpPinger> IcmpPingerItem;
-
 #endif // ICMP_PINGER_H
index 3b69d10..6c5f4b1 100644 (file)
@@ -308,7 +308,7 @@ void stop_pingers(
         scheduler->stop_pinging();
     }
 
-    IcmpPaketDistributor::clean_up_all();
+    IcmpPacketDistributor::clean_up_all();
 }