From: Guilherme Maciel Ferreira Date: Sat, 12 Nov 2011 03:01:50 +0000 (-0200) Subject: Simplifying Network Interface class and using more Boost.Asio objects X-Git-Tag: v1.2~23 X-Git-Url: http://developer.intra2net.com/git/?a=commitdiff_plain;h=d14043de09fef50a157f33a826c7151d91162c36;p=pingcheck Simplifying Network Interface class and using more Boost.Asio objects --- diff --git a/src/host/networkinterface.hpp b/src/host/networkinterface.hpp index f50fd92..09c16d2 100644 --- a/src/host/networkinterface.hpp +++ b/src/host/networkinterface.hpp @@ -41,6 +41,12 @@ #include +#include "host/networkinterfacelist.h" + +typedef const struct sockaddr* const_sockaddr_ptr_t; +typedef const struct sockaddr_in* const_sockaddr_in_ptr_t; +typedef const struct sockaddr_in6* const_sockaddr_in6_ptr_t; + //----------------------------------------------------------------------------- // NetworkInterface //----------------------------------------------------------------------------- @@ -48,7 +54,7 @@ /** * @brief This class represents a local network interface. */ -template +template class NetworkInterface { public: @@ -62,7 +68,9 @@ public: std::string get_name() const; - boost::asio::ip::address get_address(bool is_ip4) const; + boost::asio::ip::address get_address( Protocol protocol ) const; + + const uint8_t* get_address_bytes( const_sockaddr_ptr_t ifa_addr ) const; private: /// The network interface name which the socket is attached @@ -77,8 +85,8 @@ private: // NetworkInterface //----------------------------------------------------------------------------- -template -NetworkInterface::NetworkInterface( +template +NetworkInterface::NetworkInterface( const std::string &nic_name, SocketType &boost_socket ) : @@ -95,8 +103,8 @@ NetworkInterface::NetworkInterface( * * @return true if the bind was successfully, and false if the bind failed. */ -template -bool NetworkInterface::bind() +template +bool NetworkInterface::bind() { BOOST_ASSERT( !Name.empty() ); @@ -122,107 +130,88 @@ bool NetworkInterface::bind() * * @return A string representing the name of the network interface. */ -template -std::string NetworkInterface::get_name() const +template +std::string NetworkInterface::get_name() const { + BOOST_ASSERT( !Name.empty() ); + return Name; } -#include - /** * @brief This method gets the local address of network interface. * - * @return The integer IPv4 representing the local address of the network - * interface. + * @return The @c boost::asio::ip::address representing the local address of + * the network interface. */ -template -boost::asio::ip::address NetworkInterface::get_address(bool is_ip4) const +template +boost::asio::ip::address NetworkInterface::get_address( + Protocol protocol +) const { -#if 0 - struct ifreq ifr; - memset( &ifr, 0, sizeof(ifr) ); - - // make sure the ifr.ifr_name has enough room to receive the network - // interface name - size_t network_interface_name_limit = sizeof(ifr.ifr_name); - if ( network_interface_name_limit <= Name.size() ) - { - I2n::Logger::GlobalLogger.error() - << "Error: network interface name truncated" << std::endl; - return 0; - } + BOOST_ASSERT( (protocol.family() == PF_INET) || (protocol.family() == PF_INET6) ); - strncpy( ifr.ifr_name, Name.c_str(), network_interface_name_limit ); - ifr.ifr_addr.sa_family = AF_INET6; // TODO change to AF_INET6 when IPv6 -> NAO FUNCIONOU, USAR O addr6.cpp + NetworkInterfaceList nic_list; - int ioctl_resp = ioctl( Socket.native(), SIOCGIFADDR, &ifr ); - if ( ioctl_resp != 0) + const sa_family_t addr_type = static_cast( protocol.family() ); + const struct ifaddrs *ifa_entry = nic_list.find_interface( get_name(), addr_type ); + if ( ifa_entry == NULL ) { - I2n::Logger::GlobalLogger.error() - << "Error: could not retrieve IP address from network interface" - << std::endl; - return 0; + return boost::asio::ip::address(); } - const sockaddr_in *source_sockaddr = reinterpret_cast( &ifr.ifr_addr ); - uint32_t source_ipv4_address = htonl( source_sockaddr->sin_addr.s_addr ); - - std::cout << source_ipv4_address << std::endl; - - return source_ipv4_address; -#endif - - struct ifaddrs *ifa_first = NULL; - struct ifaddrs *ifa_current = NULL; - int rc = 0; - char addr_string[ INET6_ADDRSTRLEN ]; - - rc = getifaddrs( &ifa_first ); - if ( rc == 0 ) + const uint8_t *addr_bytes = get_address_bytes( ifa_entry->ifa_addr ); + if ( addr_bytes != NULL ) { - for ( ifa_current = ifa_first; ifa_current != NULL; ifa_current = ifa_current->ifa_next ) + BOOST_ASSERT( ifa_entry->ifa_addr->sa_family == addr_type ); + + char addr_buffer_string[ INET6_ADDRSTRLEN ]; + volatile const char *addr_ret_string = inet_ntop( addr_type, addr_bytes, addr_buffer_string, sizeof(addr_buffer_string) ); + if ( addr_ret_string != NULL ) { - if ( ifa_current->ifa_addr->sa_data == NULL) + if ( PF_INET == addr_type ) { - continue; + return boost::asio::ip::address_v4::from_string( std::string( addr_buffer_string ) ); } - - char *interface_name = ifa_current->ifa_name; - if ( Name == interface_name ) + else if ( PF_INET6 == addr_type ) { - sa_family_t addr_type = ifa_current->ifa_addr->sa_family; - void *addr_bytes = NULL; - - if ( AF_INET == addr_type ) - { - addr_bytes = &((struct sockaddr_in *) ifa_current->ifa_addr)->sin_addr; - } - else if ( AF_INET6 == addr_type ) - { - addr_bytes = &((struct sockaddr_in6 *) ifa_current->ifa_addr)->sin6_addr; - } - - if ( addr_bytes != NULL ) - { - const char *a = inet_ntop( addr_type, addr_bytes, addr_string, sizeof(addr_string) ); - if ( a != NULL ) - { - if ( AF_INET == addr_type ) - { - return boost::asio::ip::address_v4::from_string( std::string( a ) ); - } - else if ( AF_INET6 == addr_type ) - { - return boost::asio::ip::address_v6::from_string( std::string( a ) ); - } - } - } + return boost::asio::ip::address_v6::from_string( std::string( addr_buffer_string ) ); } } } - freeifaddrs( ifa_first ); + return boost::asio::ip::address(); +} + +/** + * @brief Converts @c sockaddr into a sequence of bytes. + * + * @param ifa_addr A @c sockaddr structure. + * + * @return A sequence of bytes representing the interface address. + */ +template +const uint8_t* NetworkInterface::get_address_bytes( + const_sockaddr_ptr_t ifa_addr +) const +{ + BOOST_ASSERT( ifa_addr != NULL ); + + sa_family_t addr_type = ifa_addr->sa_family; + const uint8_t *addr_bytes = NULL; + + if ( PF_INET == addr_type ) + { + const_sockaddr_in_ptr_t sockaddr = reinterpret_cast( ifa_addr ); + addr_bytes = reinterpret_cast( & (sockaddr->sin_addr) ); + } + else if ( PF_INET6 == addr_type ) + { + const_sockaddr_in6_ptr_t sockaddr = reinterpret_cast( ifa_addr ); + addr_bytes = reinterpret_cast( & (sockaddr->sin6_addr) ); + } + + return addr_bytes; } #endif // NETWORK_INTERFACE_HPP diff --git a/src/icmp/icmppinger.h b/src/icmp/icmppinger.h index baeaf37..57b5edb 100644 --- a/src/icmp/icmppinger.h +++ b/src/icmp/icmppinger.h @@ -63,7 +63,7 @@ private: /// The socket object boost::asio::ip::icmp::socket Socket; /// This object represents the network interface - NetworkInterface NetInterface; + NetworkInterface NetInterface; /// The timer of ICMP packet receive, triggers the timeout to avoid infinite /// wait boost::asio::deadline_timer IcmpPacketReceiveTimer; diff --git a/src/tcp/tcppinger.h b/src/tcp/tcppinger.h index 0fd46a1..f85fc15 100644 --- a/src/tcp/tcppinger.h +++ b/src/tcp/tcppinger.h @@ -85,7 +85,7 @@ private: /// the socket object boost::asio::ip::tcp_raw_protocol::socket Socket; /// This object represents the network interface - NetworkInterface NetInterface; + NetworkInterface NetInterface; /// the timer of TCP segment receive, triggers the timeout to avoid infinite /// wait boost::asio::deadline_timer TcpSegmentReceiveTimer;