From 4606d2b119d4683c356512ab8d0237eec688bb2b Mon Sep 17 00:00:00 2001 From: Christian Herdtweck Date: Mon, 26 Jan 2015 15:17:32 +0100 Subject: [PATCH] Pinger holds weak_ptr to self, Pingers created through static create functions; IcmpPinger::create registers with IcmpPaketDistributor --- src/host/pinger.cpp | 10 ++++++++++ src/host/pinger.h | 13 +++++++++++++ src/host/pingerfactory.cpp | 30 ++++++++++++++---------------- src/icmp/icmppinger.cpp | 27 ++++++++++++++++++++++++++- src/icmp/icmppinger.h | 12 +++++++++++- src/tcp/tcppinger.cpp | 19 +++++++++++++++++++ src/tcp/tcppinger.h | 20 ++++++++++++++------ 7 files changed, 107 insertions(+), 24 deletions(-) diff --git a/src/host/pinger.cpp b/src/host/pinger.cpp index df49629..224043a 100644 --- a/src/host/pinger.cpp +++ b/src/host/pinger.cpp @@ -37,3 +37,13 @@ Pinger::Pinger() Pinger::~Pinger() { } + +void Pinger::set_myself( const Pinger::WeakPtr &myself) +{ + Myself = myself; +} + +Pinger::WeakPtr Pinger::get_myself() const +{ + return Myself; +} diff --git a/src/host/pinger.h b/src/host/pinger.h index b8bdd91..705e40e 100644 --- a/src/host/pinger.h +++ b/src/host/pinger.h @@ -29,6 +29,7 @@ #include #include #include +#include //----------------------------------------------------------------------------- // IoServiceItem @@ -43,10 +44,15 @@ typedef boost::shared_ptr IoServiceItem; /** * @brief Abstract class for pingers. * Scope: one object per host. + * + * Holds a weak_ptr to itself, so can create shared_ptrs from self + * (adapted from amime project) */ class Pinger : boost::noncopyable { public: + typedef boost::weak_ptr WeakPtr; + virtual void ping( const std::string &destination_ip, const uint16_t destination_port, @@ -58,8 +64,15 @@ public: protected: Pinger(); virtual ~Pinger(); + + Pinger::WeakPtr get_myself() const; + void set_myself(const Pinger::WeakPtr &myself); + +private: + Pinger::WeakPtr Myself; }; + //----------------------------------------------------------------------------- // PingerItem //----------------------------------------------------------------------------- diff --git a/src/host/pingerfactory.cpp b/src/host/pingerfactory.cpp index 776a8b2..17285a2 100644 --- a/src/host/pingerfactory.cpp +++ b/src/host/pingerfactory.cpp @@ -82,33 +82,31 @@ PingerItem PingerFactory::createPinger( { if (protocol == PingProtocol_ICMP) { - PingerItem new_pinger( - new IcmpPinger( io_serv, icmp::v4(), network_interface, ping_reply_timeout ) - ); - IcmpPaketDistributor::get_distributor(icmp::v4(), network_interface, io_serv) - ->register_pinger(new_pinger); + PingerItem new_pinger = IcmpPinger::create( io_serv, icmp::v4(), + network_interface, + ping_reply_timeout ); return new_pinger; } else if (protocol == PingProtocol_ICMPv6) { - PingerItem new_pinger( - new IcmpPinger( io_serv, icmp::v6(), network_interface, ping_reply_timeout ) - ); - IcmpPaketDistributor::get_distributor(icmp::v6(), network_interface, io_serv) - ->register_pinger(new_pinger); + PingerItem new_pinger = IcmpPinger::create( io_serv, icmp::v6(), + network_interface, + ping_reply_timeout ); return new_pinger; } else if (protocol == PingProtocol_TCP) { - return PingerItem( - new TcpPinger( io_serv, tcp_raw_protocol::v4(), network_interface, ping_reply_timeout ) - ); + PingerItem new_pinger = TcpPinger::create( io_serv, tcp_raw_protocol::v4(), + network_interface, + ping_reply_timeout ); + return new_pinger; } else if (protocol == PingProtocol_TCP_IPv6) { - return PingerItem( - new TcpPinger( io_serv, tcp_raw_protocol::v6(), network_interface, ping_reply_timeout ) - ); + PingerItem new_pinger = TcpPinger::create( io_serv, tcp_raw_protocol::v6(), + network_interface, + ping_reply_timeout ); + return new_pinger; } else { diff --git a/src/icmp/icmppinger.cpp b/src/icmp/icmppinger.cpp index 92b6560..8a43eed 100644 --- a/src/icmp/icmppinger.cpp +++ b/src/icmp/icmppinger.cpp @@ -131,7 +131,7 @@ void IcmpPinger::ping( void IcmpPinger::stop_pinging() { IcmpPaketDistributor::get_distributor(Protocol, NetInterface.get_name()) - ->unregister_pinger(PingerItem(this)); + ->unregister_pinger( get_myself().lock() ); } @@ -390,3 +390,28 @@ 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; +} + diff --git a/src/icmp/icmppinger.h b/src/icmp/icmppinger.h index 61cab02..1ad9b63 100644 --- a/src/icmp/icmppinger.h +++ b/src/icmp/icmppinger.h @@ -31,12 +31,13 @@ class IcmpPinger : public Pinger { public: - IcmpPinger( + static PingerItem create( 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 ); + virtual ~IcmpPinger(); virtual void ping( @@ -48,6 +49,13 @@ public: virtual void stop_pinging(); 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 + ); + void set_destination_endpoint( const std::string &destination_ip ); bool start_send(); @@ -93,4 +101,6 @@ private: bool ReceiveHandlerInPlace; }; +typedef boost::shared_ptr IcmpPingerItem; + #endif // ICMP_PINGER_H diff --git a/src/tcp/tcppinger.cpp b/src/tcp/tcppinger.cpp index 1b43a62..79347f6 100644 --- a/src/tcp/tcppinger.cpp +++ b/src/tcp/tcppinger.cpp @@ -333,3 +333,22 @@ void TcpPinger::set_ping_status( PingStatus ping_status ) { PingerStatus = ping_status; } + +PingerItem TcpPinger::create( + const IoServiceItem io_serv, + const tcp_raw_protocol::socket::protocol_type &protocol, + const string &source_network_interface_name, + const int rst_reply_timeout_in_sec ) +{ + TcpPinger *ptr = new TcpPinger(io_serv, protocol, source_network_interface_name, + rst_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 + + // done, return shared ptr + return shared_ptr; +} diff --git a/src/tcp/tcppinger.h b/src/tcp/tcppinger.h index d579cd9..8a6329f 100644 --- a/src/tcp/tcppinger.h +++ b/src/tcp/tcppinger.h @@ -44,12 +44,6 @@ on this file might be covered by the GNU General Public License. class TcpPinger : public Pinger { public: - TcpPinger( - const IoServiceItem io_serv, - const boost::asio::ip::tcp_raw_protocol::socket::protocol_type &protocol, - const std::string &source_network_interface_name, - const int rst_reply_timeout_in_sec - ); virtual ~TcpPinger(); virtual void ping( @@ -60,7 +54,21 @@ public: virtual void stop_pinging(); + static PingerItem create( + const IoServiceItem io_serv, + const boost::asio::ip::tcp_raw_protocol::socket::protocol_type &protocol, + const std::string &source_network_interface_name, + const int rst_reply_timeout_in_sec + ); + private: + TcpPinger( + const IoServiceItem io_serv, + const boost::asio::ip::tcp_raw_protocol::socket::protocol_type &protocol, + const std::string &source_network_interface_name, + const int rst_reply_timeout_in_sec + ); + boost::asio::ip::address get_source_address() const; boost::asio::ip::address get_destination_address() const; -- 1.7.1