more improvements/redesign, mostly Windows related

This commit is contained in:
Aleksandar Fabijanic 2012-08-13 01:58:35 +00:00
Родитель 20d5b2d2fb
Коммит 273b9c92f8
6 изменённых файлов: 288 добавлений и 117 удалений

Просмотреть файл

@ -89,7 +89,9 @@ public:
IPv4_OR_IPv6 /// Return interfaces with IPv4 or IPv6 address IPv4_OR_IPv6 /// Return interfaces with IPv4 or IPv6 address
}; };
NetworkInterface(unsigned index = 0); static const unsigned NO_INDEX = ~0;
NetworkInterface(unsigned index = NO_INDEX);
/// Creates a NetworkInterface representing the /// Creates a NetworkInterface representing the
/// default interface. /// default interface.
/// ///
@ -129,8 +131,11 @@ public:
/// ///
/// On other platforms this is the same as name(). /// On other platforms this is the same as name().
const IPAddress& address(unsigned index = 0) const; const IPAddress& findFirstAddress(IPAddress::Family family) const;
/// Returns the IP address bound to the interface. /// Returns the first IP address bound to the interface.
const IPAddress& address(unsigned index) const;
/// Returns the IP address bound to the interface at index position.
void addAddress(const IPAddress& address); void addAddress(const IPAddress& address);
/// Adds address to the interface. /// Adds address to the interface.
@ -141,13 +146,13 @@ public:
const AddressList& addressList() const; const AddressList& addressList() const;
/// Returns the list of IP addresses bound to the interface. /// Returns the list of IP addresses bound to the interface.
const IPAddress& subnetMask(unsigned index = 0) const; const IPAddress& subnetMask(unsigned index) const;
/// Returns the subnet mask for this network interface. /// Returns the subnet mask for this network interface.
const IPAddress& broadcastAddress(unsigned index = 0) const; const IPAddress& broadcastAddress(unsigned index) const;
/// Returns the broadcast address for this network interface. /// Returns the broadcast address for this network interface.
const IPAddress& destAddress(unsigned index = 0) const; const IPAddress& destAddress(unsigned index) const;
/// Returns the IPv4 point-to-point destiation address for this network interface. /// Returns the IPv4 point-to-point destiation address for this network interface.
const MacAddress& macAddress() const; const MacAddress& macAddress() const;
@ -217,26 +222,50 @@ public:
/// with the given index does not exist (or IPv6 is not /// with the given index does not exist (or IPv6 is not
/// available). /// available).
static Map map(); static List list(bool ipOnly = true, bool upOnly = true);
/// Returns a map with all network interfaces /// Returns a list with all network interfaces
/// on the system. Map is keyed by interface system /// on the system.
/// indices. ///
/// If ipOnly is true, only interfaces supporting IP
/// are returned. Otherwise, all system network interfaces
/// are returned.
///
/// If upOnly is true, only interfaces being up are returned.
/// Otherwise, both interfaces being up and down are returned.
///
/// If there are multiple addresses bound to one interface,
/// multiple NetworkInterface entries are listed for
/// the same interface.
static Map map(bool ipOnly = true, bool upOnly = true);
/// Returns a map containing system network interfaces
/// Map is keyed by interface system indices.
///
/// If ipOnly is true, only interfaces supporting IP
/// are returned. Otherwise, all system network interfaces
/// are returned.
///
/// If upOnly is true, only interfaces being up are returned.
/// Otherwise, both interfaces being up and down are returned.
/// ///
/// If there are multiple addresses bound to one interface, /// If there are multiple addresses bound to one interface,
/// they are contained within the NetworkInterface (second) /// they are contained within the NetworkInterface (second)
/// member of the pair. /// member of the pair.
protected: protected:
NetworkInterface(const std::string& name, const std::string& displayName, const IPAddress& address, unsigned index = 0); NetworkInterface(const std::string& name, const std::string& displayName, const IPAddress& address, unsigned index);
/// Creates the NetworkInterface. /// Creates the NetworkInterface.
NetworkInterface(const std::string& name, const std::string& displayName, const IPAddress& address, const IPAddress& subnetMask, const IPAddress& broadcastAddress, unsigned index = 0); NetworkInterface(const std::string& name, const std::string& displayName, unsigned index);
/// Creates the NetworkInterface. /// Creates the NetworkInterface.
NetworkInterface(const std::string& name, const IPAddress& address, unsigned index = 0); NetworkInterface(const std::string& name, const IPAddress& address, unsigned index);
/// Creates the NetworkInterface. /// Creates the NetworkInterface.
NetworkInterface(const std::string& name, const IPAddress& address, const IPAddress& subnetMask, const IPAddress& broadcastAddress, unsigned index = 0); NetworkInterface(const std::string& name, const std::string& displayName, const IPAddress& address, const IPAddress& subnetMask, const IPAddress& broadcastAddress, unsigned index);
/// Creates the NetworkInterface.
NetworkInterface(const std::string& name, const IPAddress& address, const IPAddress& subnetMask, const IPAddress& broadcastAddress, unsigned index);
/// Creates the NetworkInterface. /// Creates the NetworkInterface.
IPAddress interfaceNameToAddress(const std::string& interfaceName) const; IPAddress interfaceNameToAddress(const std::string& interfaceName) const;

Просмотреть файл

@ -99,7 +99,7 @@ void MulticastSocket::setInterface(const NetworkInterface& interfc)
{ {
if (!interfc.supportsIPv6()) if (!interfc.supportsIPv6())
{ {
impl()->setOption(IPPROTO_IP, IP_MULTICAST_IF, interfc.address()); impl()->setOption(IPPROTO_IP, IP_MULTICAST_IF, interfc.findFirstAddress(IPAddress::IPv4));
} }
else else
{ {
@ -217,7 +217,7 @@ void MulticastSocket::joinGroup(const IPAddress& groupAddress, const NetworkInte
{ {
struct ip_mreq mr; struct ip_mreq mr;
std::memcpy(&mr.imr_multiaddr, groupAddress.addr(), groupAddress.length()); std::memcpy(&mr.imr_multiaddr, groupAddress.addr(), groupAddress.length());
std::memcpy(&mr.imr_interface, interfc.address().addr(), interfc.address().length()); std::memcpy(&mr.imr_interface, interfc.findFirstAddress(IPAddress::IPv4).addr(), interfc.findFirstAddress(IPAddress::IPv4).length());
impl()->setRawOption(IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr, sizeof(mr)); impl()->setRawOption(IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr, sizeof(mr));
} }
else else
@ -245,7 +245,7 @@ void MulticastSocket::leaveGroup(const IPAddress& groupAddress, const NetworkInt
{ {
struct ip_mreq mr; struct ip_mreq mr;
std::memcpy(&mr.imr_multiaddr, groupAddress.addr(), groupAddress.length()); std::memcpy(&mr.imr_multiaddr, groupAddress.addr(), groupAddress.length());
std::memcpy(&mr.imr_interface, interfc.address().addr(), interfc.address().length()); std::memcpy(&mr.imr_interface, interfc.findFirstAddress(IPAddress::IPv4).addr(), interfc.findFirstAddress(IPAddress::IPv4).length());
impl()->setRawOption(IPPROTO_IP, IP_DROP_MEMBERSHIP, &mr, sizeof(mr)); impl()->setRawOption(IPPROTO_IP, IP_DROP_MEMBERSHIP, &mr, sizeof(mr));
} }
else else

Просмотреть файл

@ -70,20 +70,22 @@ public:
typedef NetworkInterface::AddressTuple AddressTuple; typedef NetworkInterface::AddressTuple AddressTuple;
typedef NetworkInterface::AddressList AddressList; typedef NetworkInterface::AddressList AddressList;
NetworkInterfaceImpl(unsigned index = 0); NetworkInterfaceImpl(unsigned index);
NetworkInterfaceImpl(const std::string& name, const std::string& displayName, const IPAddress& address, unsigned index = 0); NetworkInterfaceImpl(const std::string& name, const std::string& displayName, const IPAddress& address, unsigned index);
NetworkInterfaceImpl(const std::string& name, const std::string& displayName, const IPAddress& address, const IPAddress& subnetMask, const IPAddress& broadcastAddress, unsigned index = 0); NetworkInterfaceImpl(const std::string& name, const std::string& displayName, unsigned index = 0);
NetworkInterfaceImpl(const std::string& name, const std::string& displayName, const IPAddress& address, const IPAddress& subnetMask, const IPAddress& broadcastAddress, unsigned index);
unsigned index() const; unsigned index() const;
const std::string& name() const; const std::string& name() const;
const std::string& displayName() const; const std::string& displayName() const;
const IPAddress& findFirstAddress(IPAddress::Family family) const;
void addAddress(const AddressTuple& address); void addAddress(const AddressTuple& address);
const IPAddress& address(unsigned index = 0) const; const IPAddress& address(unsigned index) const;
const NetworkInterface::AddressList& addressList() const; const NetworkInterface::AddressList& addressList() const;
bool hasAddress(const IPAddress& address) const; bool hasAddress(const IPAddress& address) const;
const IPAddress& subnetMask(unsigned index = 0) const; const IPAddress& subnetMask(unsigned index) const;
const IPAddress& broadcastAddress(unsigned index = 0) const; const IPAddress& broadcastAddress(unsigned index) const;
const IPAddress& destAddress(unsigned index = 0) const; const IPAddress& destAddress(unsigned index) const;
const NetworkInterface::MacAddress& macAddress() const; const NetworkInterface::MacAddress& macAddress() const;
bool supportsIPv4() const; bool supportsIPv4() const;
bool supportsIPv6() const; bool supportsIPv6() const;
@ -137,7 +139,7 @@ private:
NetworkInterface::MacAddress _macAddress; NetworkInterface::MacAddress _macAddress;
friend NetworkInterface::Map NetworkInterface::map(); friend NetworkInterface::Map NetworkInterface::map(bool, bool);
}; };
@ -166,6 +168,23 @@ NetworkInterfaceImpl::NetworkInterfaceImpl(const std::string& name, const std::s
} }
NetworkInterfaceImpl::NetworkInterfaceImpl(const std::string& name, const std::string& displayName, unsigned index):
_name(name),
_displayName(displayName),
_index(index),
_broadcast(false),
_loopback(false),
_multicast(false),
_pointToPoint(false),
_up(false),
_running(false),
_mtu(0)
{
getPhyParams();
if (_pointToPoint) getPeerAddress();
}
NetworkInterfaceImpl::NetworkInterfaceImpl(const std::string& name, const std::string& displayName, const IPAddress& address, const IPAddress& subnetMask, const IPAddress& broadcastAddress, unsigned index): NetworkInterfaceImpl::NetworkInterfaceImpl(const std::string& name, const std::string& displayName, const IPAddress& address, const IPAddress& subnetMask, const IPAddress& broadcastAddress, unsigned index):
_name(name), _name(name),
_displayName(displayName), _displayName(displayName),
@ -275,6 +294,23 @@ inline const std::string& NetworkInterfaceImpl::displayName() const
} }
const IPAddress& NetworkInterfaceImpl::findFirstAddress(IPAddress::Family family) const
{
if (!supportsIPv4() && !supportsIPv6())
throw NotImplementedException("Unknown or unsupported family.");
AddressList::const_iterator it = _addressList.begin();
AddressList::const_iterator end = _addressList.end();
for (;it != end; ++it)
{
const IPAddress& addr = it->get<NetworkInterface::IP_ADDRESS>();
if (addr.family() == family) return addr;
}
throw NotFoundException(format("%s family address not found.", family == IPAddress::IPv4 ? "IPv4" : "IPv6"));
}
inline void NetworkInterfaceImpl::addAddress(const AddressTuple& address) inline void NetworkInterfaceImpl::addAddress(const AddressTuple& address)
{ {
_addressList.push_back(address); _addressList.push_back(address);
@ -514,8 +550,8 @@ NetworkInterface::NetworkInterface(const std::string& name, const std::string& d
} }
NetworkInterface::NetworkInterface(const std::string& name, const std::string& displayName, const IPAddress& address, const IPAddress& subnetMask, const IPAddress& broadcastAddress, unsigned index): NetworkInterface::NetworkInterface(const std::string& name, const std::string& displayName, unsigned index):
_pImpl(new NetworkInterfaceImpl(name, displayName, address, subnetMask, broadcastAddress, index)) _pImpl(new NetworkInterfaceImpl(name, displayName, index))
{ {
} }
@ -526,6 +562,12 @@ NetworkInterface::NetworkInterface(const std::string& name, const IPAddress& add
} }
NetworkInterface::NetworkInterface(const std::string& name, const std::string& displayName, const IPAddress& address, const IPAddress& subnetMask, const IPAddress& broadcastAddress, unsigned index):
_pImpl(new NetworkInterfaceImpl(name, displayName, address, subnetMask, broadcastAddress, index))
{
}
NetworkInterface::NetworkInterface(const std::string& name, const IPAddress& address, const IPAddress& subnetMask, const IPAddress& broadcastAddress, unsigned index): NetworkInterface::NetworkInterface(const std::string& name, const IPAddress& address, const IPAddress& subnetMask, const IPAddress& broadcastAddress, unsigned index):
_pImpl(new NetworkInterfaceImpl(name, name, address, subnetMask, broadcastAddress, index)) _pImpl(new NetworkInterfaceImpl(name, name, address, subnetMask, broadcastAddress, index))
{ {
@ -571,6 +613,12 @@ const std::string& NetworkInterface::displayName() const
} }
const IPAddress& NetworkInterface::findFirstAddress(IPAddress::Family family) const
{
return _pImpl->findFirstAddress(family);
}
void NetworkInterface::addAddress(const IPAddress& address) void NetworkInterface::addAddress(const IPAddress& address)
{ {
_pImpl->addAddress(AddressTuple(address, IPAddress(), IPAddress())); _pImpl->addAddress(AddressTuple(address, IPAddress(), IPAddress()));
@ -741,48 +789,55 @@ NetworkInterface NetworkInterface::forAddress(const IPAddress& addr)
NetworkInterface NetworkInterface::forIndex(unsigned i) NetworkInterface NetworkInterface::forIndex(unsigned i)
{ {
if (i != 0) if (i != NetworkInterface::NO_INDEX)
{ {
Map map = NetworkInterface::map(); Map map = NetworkInterface::map();
Map::const_iterator it = map.find(i); Map::const_iterator it = map.find(i);
if (it != map.end()) if (it != map.end())
return it->second; return it->second;
else
throw InterfaceNotFoundException("#" + NumberFormatter::format(i));
} }
throw InterfaceNotFoundException("#" + NumberFormatter::format(i)); throw InterfaceNotFoundException("#" + NumberFormatter::format(i));
} }
#if (POCO_OS == POCO_OS_LINUX)
#include <net/if_arp.h> NetworkInterface::List NetworkInterface::list(bool ipOnly, bool upOnly)
static unsigned arphrdToIfType(unsigned arphrd)
{ {
switch (arphrd) { List list;
case ARPHRD_ETHER: Map m = map(ipOnly, upOnly);
return 6; // IF_TYPE_ETHERNET_CSMACD NetworkInterface::Map::const_iterator it = m.begin();
case ARPHRD_IEEE802: NetworkInterface::Map::const_iterator end = m.end();
return 9; // IF_TYPE_ISO88025_TOKENRING for (; it != end; ++it)
case ARPHRD_DLCI: {
return 32; // IF_TYPE_FRAMERELAY int index = it->second.index();
case ARPHRD_PPP: std::string name = it->second.name();
return 512; // IF_TYPE_PPP std::string displayName = it->second.displayName();
case ARPHRD_LOOPBACK:
return 24; // IF_TYPE_SOFTWARE_LOOPBACK typedef NetworkInterface::AddressList List;
case ARPHRD_ATM: const List& ipList = it->second.addressList();
return 37; // IF_TYPE_ATM List::const_iterator ipIt = ipList.begin();
case ARPHRD_IEEE80211: List::const_iterator ipEnd = ipList.end();
return 71; // IF_TYPE_IEEE80211 for (int counter = 0; ipIt != ipEnd; ++ipIt, ++counter)
case ARPHRD_TUNNEL: {
case ARPHRD_TUNNEL6: IPAddress addr = ipIt->get<NetworkInterface::IP_ADDRESS>();
return 131; // IF_TYPE_TUNNEL IPAddress mask = ipIt->get<NetworkInterface::SUBNET_MASK>();
case ARPHRD_IEEE1394: NetworkInterface ni;
return 144; // IF_TYPE_IEEE1394 if (mask.isWildcard())
default: ni = NetworkInterface(name, displayName, addr, index);
return 1; // IF_TYPE_OTHER else
{
IPAddress broadcast = ipIt->get<NetworkInterface::BROADCAST_ADDRESS>();
ni = NetworkInterface(name, displayName, addr, mask, broadcast, index);
}
list.push_back(ni);
}
} }
return list;
} }
#endif
} } // namespace Poco::Net } } // namespace Poco::Net
@ -860,7 +915,7 @@ std::string getErrorMessage(DWORD errorCode)
} /// namespace } /// namespace
NetworkInterface::Map NetworkInterface::map() NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly)
{ {
FastMutex::ScopedLock lock(_mutex); FastMutex::ScopedLock lock(_mutex);
Map result; Map result;
@ -897,67 +952,72 @@ NetworkInterface::Map NetworkInterface::map()
IPAddress subnetMask; IPAddress subnetMask;
IPAddress broadcastAddress; IPAddress broadcastAddress;
unsigned ifIndex = 0; unsigned ifIndex = 0;
//
// Create interface even if it has an empty list of addresses; also, set
// physical attributes which are protocol independent (name, media type,
// MAC address, MTU, operational status, etc).
//
Map::iterator ifIt = result.insert(Map::value_type(ifInex, NetworkInterface(name, displayName, ifIndex);
ifIt->second.impl().setFlags(pAddress->Flags, pAddress->IfType);
ifIt->second.impl().setMtu(pAddress->Mtu);
ifIt->second.impl().setUp(pAddress->OperStatus == IfOperStatusUp);
ifIt->second.impl().setMacAddress(pAddress->PhysicalAddress, pAddress->PhysicalAddressLength);
ifIt->second.impl().setHWType(pAddress->IfType);
#if defined(POCO_HAVE_IPv6) #if defined(POCO_HAVE_IPv6)
poco_assert (pAddress->Ipv6IfIndex == pAddress->IfIndex);
if (pAddress->Flags & IP_ADAPTER_IPV6_ENABLED) ifIndex = pAddress->Ipv6IfIndex; if (pAddress->Flags & IP_ADAPTER_IPV6_ENABLED) ifIndex = pAddress->Ipv6IfIndex;
else else
#endif #endif
if (pAddress->Flags & IP_ADAPTER_IPV4_ENABLED) ifIndex = pAddress->IfIndex; if (pAddress->Flags & IP_ADAPTER_IPV4_ENABLED) ifIndex = pAddress->IfIndex;
for (PIP_ADAPTER_UNICAST_ADDRESS pUniAddr = pAddress->FirstUnicastAddress; std::string name(pAddress->AdapterName);
pUniAddr; std::string displayName;
pUniAddr = pUniAddr->Next)
{
std::string name(pAddress->AdapterName);
std::string displayName;
#ifdef POCO_WIN32_UTF8 #ifdef POCO_WIN32_UTF8
Poco::UnicodeConverter::toUTF8(pAddress->FriendlyName, displayName); Poco::UnicodeConverter::toUTF8(pAddress->FriendlyName, displayName);
#else #else
char displayNameBuffer[1024]; char displayNameBuffer[1024];
int rc = WideCharToMultiByte(CP_ACP, WC_DEFAULTCHAR, pAddress->FriendlyName, -1, displayNameBuffer, sizeof(displayNameBuffer), NULL, NULL); int rc = WideCharToMultiByte(CP_ACP, WC_DEFAULTCHAR, pAddress->FriendlyName, -1, displayNameBuffer, sizeof(displayNameBuffer), NULL, NULL);
if (rc) displayName = displayNameBuffer; if (rc) displayName = displayNameBuffer;
#endif #endif
UINT8 prefixLength = pUniAddr->OnLinkPrefixLength;
address = IPAddress(pUniAddr->Address); bool isUp = (pAddress->OperStatus == IfOperStatusUp);
ADDRESS_FAMILY family = pUniAddr->Address.lpSockaddr->sa_family; bool isIP = (0 != pAddress->FirstUnicastAddress);
switch (family) if (((ipOnly && isIP) || !ipOnly) && ((upOnly && isUp) || !upOnly))
{
NetworkInterface ni(name, displayName, ifIndex);
// Create interface even if it has an empty list of addresses; also, set
// physical attributes which are protocol independent (name, media type,
// MAC address, MTU, operational status, etc).
Map::iterator ifIt = result.find(ifIndex);
if (ifIt == result.end())
ifIt = result.insert(Map::value_type(ifIndex, ni)).first;
ifIt->second.impl().setFlags(pAddress->Flags, pAddress->IfType);
ifIt->second.impl().setMtu(pAddress->Mtu);
ifIt->second.impl().setUp(pAddress->OperStatus == IfOperStatusUp);
ifIt->second.impl().setHWType(pAddress->IfType);
if (pAddress->PhysicalAddressLength)
ifIt->second.impl().setMacAddress(pAddress->PhysicalAddress, pAddress->PhysicalAddressLength);
for (PIP_ADAPTER_UNICAST_ADDRESS pUniAddr = pAddress->FirstUnicastAddress;
pUniAddr;
pUniAddr = pUniAddr->Next)
{ {
case AF_INET: UINT8 prefixLength = pUniAddr->OnLinkPrefixLength;
address = IPAddress(pUniAddr->Address);
ADDRESS_FAMILY family = pUniAddr->Address.lpSockaddr->sa_family;
switch (family)
{ {
// Windows lists broadcast address on localhost case AF_INET:
bool hasBroadcast = (pAddress->IfType == IF_TYPE_ETHERNET_CSMACD) || (pAddress->IfType == IF_TYPE_SOFTWARE_LOOPBACK); {
// On Windows, a valid broadcast address will be all 1's (== address | ~subnetMask); we go an extra mile here in order to // Windows lists broadcast address on localhost
// make sure we reflect the actual value held by system and protect against misconfiguration (e.g. bad DHCP config entry) bool hasBroadcast = (pAddress->IfType == IF_TYPE_ETHERNET_CSMACD) || (pAddress->IfType == IF_TYPE_SOFTWARE_LOOPBACK);
broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address); // On Windows, a valid broadcast address will be all 1's (== address | ~subnetMask); we go an extra mile here in order to
subnetMask = prefixLength ? IPAddress(prefixLength, IPAddress::IPv4) : IPAddress(); // make sure we reflect the actual value held by system and protect against misconfiguration (e.g. bad DHCP config entry)
if (hasBroadcast) broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address);
ifIt->second.addAddress(address, subnetMask, broadcastAddress); subnetMask = prefixLength ? IPAddress(prefixLength, IPAddress::IPv4) : IPAddress();
else if (hasBroadcast)
ifIt->second.addAddress(address, subnetMask, broadcastAddress);
else
ifIt->second.addAddress(address);
} break;
#if defined(POCO_HAVE_IPv6)
case AF_INET6:
ifIt->second.addAddress(address); ifIt->second.addAddress(address);
} break; break;
#if defined(POCO_HAVE_IPv6) #endif
case AF_INET6: } // switch family
{ } // for addresses
ifIt->second.addAddress(address); } // if ipOnly/upOnly
} break;
#endif
} // switch family
} // for addresses
} // for adapters } // for adapters
return result; return result;
} }
@ -1035,7 +1095,7 @@ namespace Poco {
namespace Net { namespace Net {
NetworkInterface::Map NetworkInterface::map() NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly)
{ {
FastMutex::ScopedLock lock(_mutex); FastMutex::ScopedLock lock(_mutex);
Map result; Map result;
@ -1134,13 +1194,46 @@ NetworkInterface::Map NetworkInterface::map()
#include <ifaddrs.h> #include <ifaddrs.h>
#include <linux/if.h> #include <linux/if.h>
#include <linux/if_packet.h> #include <linux/if_packet.h>
#include <net/if_arp.h>
namespace Poco { namespace Poco {
namespace Net { namespace Net {
NetworkInterface::Map NetworkInterface::map() namespace {
static unsigned arphrdToIfType(unsigned arphrd)
{
switch (arphrd) {
case ARPHRD_ETHER:
return 6; // IF_TYPE_ETHERNET_CSMACD
case ARPHRD_IEEE802:
return 9; // IF_TYPE_ISO88025_TOKENRING
case ARPHRD_DLCI:
return 32; // IF_TYPE_FRAMERELAY
case ARPHRD_PPP:
return 512; // IF_TYPE_PPP
case ARPHRD_LOOPBACK:
return 24; // IF_TYPE_SOFTWARE_LOOPBACK
case ARPHRD_ATM:
return 37; // IF_TYPE_ATM
case ARPHRD_IEEE80211:
return 71; // IF_TYPE_IEEE80211
case ARPHRD_TUNNEL:
case ARPHRD_TUNNEL6:
return 131; // IF_TYPE_TUNNEL
case ARPHRD_IEEE1394:
return 144; // IF_TYPE_IEEE1394
default:
return 1; // IF_TYPE_OTHER
}
}
}
NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly)
{ {
FastMutex::ScopedLock lock(_mutex); FastMutex::ScopedLock lock(_mutex);
Map result; Map result;

Просмотреть файл

@ -107,11 +107,16 @@ const NetworkInterface& MulticastEchoServer::interfc() const
Poco::Net::NetworkInterface MulticastEchoServer::findInterface() Poco::Net::NetworkInterface MulticastEchoServer::findInterface()
{ {
NetworkInterface::Map map = NetworkInterface::map(); NetworkInterface::Map m = NetworkInterface::map();
for (NetworkInterface::Map::const_iterator it = map.begin(); it != map.end(); ++it) for (NetworkInterface::Map::const_iterator it = m.begin(); it != m.end(); ++it)
{ {
if (it->second.supportsIPv4() && it->second.address().isUnicast() && !it->second.isLoopback() && it->second.isPointToPoint()) if (it->second.supportsIPv4() &&
it->second.findFirstAddress(IPAddress::IPv4).isUnicast() &&
!it->second.isLoopback() &&
!it->second.isPointToPoint())
{
return it->second; return it->second;
}
} }
return NetworkInterface(); return NetworkInterface();
} }

Просмотреть файл

@ -41,6 +41,7 @@
using Poco::Net::NetworkInterface; using Poco::Net::NetworkInterface;
using Poco::Net::IPAddress; using Poco::Net::IPAddress;
using Poco::NotFoundException;
NetworkInterfaceTest::NetworkInterfaceTest(const std::string& name): CppUnit::TestCase(name) NetworkInterfaceTest::NetworkInterfaceTest(const std::string& name): CppUnit::TestCase(name)
@ -55,9 +56,9 @@ NetworkInterfaceTest::~NetworkInterfaceTest()
void NetworkInterfaceTest::testMap() void NetworkInterfaceTest::testMap()
{ {
NetworkInterface::Map map = NetworkInterface::map(); NetworkInterface::Map m = NetworkInterface::map(false, false);
assert (!map.empty()); assert (!m.empty());
for (NetworkInterface::Map::const_iterator it = map.begin(); it != map.end(); ++it) for (NetworkInterface::Map::const_iterator it = m.begin(); it != m.end(); ++it)
{ {
std::cout << std::endl << "=============" << std::endl; std::cout << std::endl << "=============" << std::endl;
@ -71,7 +72,7 @@ void NetworkInterfaceTest::testMap()
std::cout << "Mac Address: (" << it->second.hwType() << ")"; std::cout << "Mac Address: (" << it->second.hwType() << ")";
for (unsigned i = 0; i < mac.size(); ++i) for (unsigned i = 0; i < mac.size(); ++i)
std::cout << ((i == 0) ? ' ' : ':') << std::hex << std::setw(2) << std::setfill('0') << (unsigned)mac[i]; std::cout << ((i == 0) ? ' ' : ':') << std::hex << std::setw(2) << std::setfill('0') << (unsigned)mac[i];
std::cout << std::endl; std::cout << std::dec << std::endl;
} }
typedef NetworkInterface::AddressList List; typedef NetworkInterface::AddressList List;
@ -95,6 +96,36 @@ void NetworkInterfaceTest::testMap()
} }
void NetworkInterfaceTest::testList()
{
NetworkInterface::List list = NetworkInterface::list();
assert (!list.empty());
for (NetworkInterface::NetworkInterfaceList::const_iterator it = list.begin(); it != list.end(); ++it)
{
std::cout << "==============" << std::endl;
std::cout << "Index: " << it->index() << std::endl;
std::cout << "Name: " << it->name() << std::endl;
std::cout << "DisplayName: " << it->displayName() << std::endl;
typedef NetworkInterface::AddressList List;
const List& ipList = it->addressList();
List::const_iterator ipIt = ipList.begin();
List::const_iterator ipEnd = ipList.end();
for (int counter = 0; ipIt != ipEnd; ++ipIt, ++counter)
{
std::cout << "IP Address: " << ipIt->get<NetworkInterface::IP_ADDRESS>().toString() << std::endl;
IPAddress addr = ipIt->get<NetworkInterface::SUBNET_MASK>();
if (!addr.isWildcard()) std::cout << "Subnet: " << ipIt->get<NetworkInterface::SUBNET_MASK>().toString() << std::endl;
addr = ipIt->get<NetworkInterface::BROADCAST_ADDRESS>();
if (!addr.isWildcard()) std::cout << "Broadcast: " << ipIt->get<NetworkInterface::BROADCAST_ADDRESS>().toString() << std::endl;
}
std::cout << "==============" << std::endl << std::endl;
}
}
void NetworkInterfaceTest::testForName() void NetworkInterfaceTest::testForName()
{ {
NetworkInterface::Map map = NetworkInterface::map(); NetworkInterface::Map map = NetworkInterface::map();
@ -112,11 +143,22 @@ void NetworkInterfaceTest::testForAddress()
for (NetworkInterface::Map::const_iterator it = map.begin(); it != map.end(); ++it) for (NetworkInterface::Map::const_iterator it = map.begin(); it != map.end(); ++it)
{ {
// not all interfaces have IP configured // not all interfaces have IP configured
if (it->second.addressList().empty()) if (it->second.addressList().empty()) continue;
continue;
NetworkInterface ifc = NetworkInterface::forAddress(it->second.address()); if (it->second.supportsIPv4())
assert (ifc.address() == it->second.address()); {
NetworkInterface ifc = NetworkInterface::forAddress(it->second.findFirstAddress(IPAddress::IPv4));
assert (ifc.findFirstAddress(IPAddress::IPv4) == it->second.findFirstAddress(IPAddress::IPv4));
}
else
{
try
{
it->second.findFirstAddress(IPAddress::IPv4);
fail ("must throw");
}
catch (NotFoundException&) { }
}
} }
} }
@ -146,6 +188,7 @@ CppUnit::Test* NetworkInterfaceTest::suite()
{ {
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("NetworkInterfaceTest"); CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("NetworkInterfaceTest");
CppUnit_addTest(pSuite, NetworkInterfaceTest, testList);
CppUnit_addTest(pSuite, NetworkInterfaceTest, testMap); CppUnit_addTest(pSuite, NetworkInterfaceTest, testMap);
CppUnit_addTest(pSuite, NetworkInterfaceTest, testForName); CppUnit_addTest(pSuite, NetworkInterfaceTest, testForName);
CppUnit_addTest(pSuite, NetworkInterfaceTest, testForAddress); CppUnit_addTest(pSuite, NetworkInterfaceTest, testForAddress);

Просмотреть файл

@ -47,6 +47,7 @@ public:
~NetworkInterfaceTest(); ~NetworkInterfaceTest();
void testMap(); void testMap();
void testList();
void testForName(); void testForName();
void testForAddress(); void testForAddress();
void testForIndex(); void testForIndex();