Permalink
Browse files

Simplify NetworkInterface::Map-based operations: get full list of int…

…erfaces as one operation, then filter based on IP/UP status as a separate operation.
  • Loading branch information...
1 parent 046bbdc commit b79e855180aec3c8bb37c5d0ab04360d63649581 @pprindeville committed Nov 21, 2012
Showing with 101 additions and 126 deletions.
  1. +8 −0 Net/include/Poco/Net/NetworkInterface.h
  2. +93 −126 Net/src/NetworkInterface.cpp
@@ -258,6 +258,14 @@ class Net_API NetworkInterface
/// multiple NetworkInterface entries are listed for
/// the same interface.
+ static Map full();
+ /// Returns a map containing system network interfaces
+ /// Map is keyed by interface system indices.
+ ///
+ /// If there are multiple addresses bound to one interface,
+ /// they are contained within the NetworkInterface (second)
+ /// member of the pair.
+
static Map map(bool ipOnly = true, bool upOnly = true);
/// Returns a map containing system network interfaces
/// Map is keyed by interface system indices.
@@ -156,7 +156,7 @@ class NetworkInterfaceImpl: public Poco::RefCountedObject
NetworkInterface::MACAddress _macAddress;
- friend NetworkInterface::Map NetworkInterface::map(bool, bool);
+ friend NetworkInterface::Map NetworkInterface::full();
};
@@ -721,7 +721,7 @@ bool NetworkInterface::isUp() const
NetworkInterface NetworkInterface::forName(const std::string& name, bool requireIPv6)
{
- Map map = NetworkInterface::map(false, false);
+ Map map = NetworkInterface::full();
Map::const_iterator it = map.begin();
Map::const_iterator end = map.end();
@@ -736,7 +736,7 @@ NetworkInterface NetworkInterface::forName(const std::string& name, bool require
NetworkInterface NetworkInterface::forName(const std::string& name, IPVersion ipVersion)
{
- Map map = NetworkInterface::map(false, false);
+ Map map = NetworkInterface::full();
Map::const_iterator it = map.begin();
Map::const_iterator end = map.end();
@@ -758,7 +758,7 @@ NetworkInterface NetworkInterface::forName(const std::string& name, IPVersion ip
NetworkInterface NetworkInterface::forAddress(const IPAddress& addr)
{
- Map map = NetworkInterface::map(true, false);
+ Map map = NetworkInterface::full();
Map::const_iterator it = map.begin();
Map::const_iterator end = map.end();
@@ -779,7 +779,7 @@ NetworkInterface NetworkInterface::forIndex(unsigned i)
{
if (i != NetworkInterface::NO_INDEX)
{
- Map map = NetworkInterface::map(false, false);
+ Map map = NetworkInterface::full();
Map::const_iterator it = map.find(i);
if (it != map.end())
return it->second;
@@ -790,6 +790,23 @@ NetworkInterface NetworkInterface::forIndex(unsigned i)
}
+NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly)
+{
+ Map m = full();
+ NetworkInterface::Map::const_iterator it = m.begin();
+ NetworkInterface::Map::const_iterator end = m.end();
+ for (; it != end; )
+ {
+ NetworkInterface::Map::const_iterator it2 = it++;
+
+ if ((ipOnly && it2->second.addressList().empty())
+ || (upOnly && !it2->second.isUp()))
+ m.erase(it2->first);
+ }
+ return m;
+}
+
+
NetworkInterface::List NetworkInterface::list(bool ipOnly, bool upOnly)
{
List list;
@@ -907,7 +924,7 @@ NetworkInterface::Type fromNative(DWORD type)
} /// namespace
-NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly)
+NetworkInterface::Map NetworkInterface::full()
{
FastMutex::ScopedLock lock(_mutex);
Map result;
@@ -975,76 +992,69 @@ NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly)
if (rc) displayName = displayNameBuffer;
#endif
- bool isUp = (pAddress->OperStatus == IfOperStatusUp);
- bool isIP = (0 != pAddress->FirstUnicastAddress);
- 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;
+ 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.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().setFlags(pAddress->Flags, pAddress->IfType);
+ ifIt->second.impl().setMTU(pAddress->Mtu);
+ ifIt->second.impl().setUp(pAddress->OperStatus == IfOperStatusUp);
#if (_WIN32_WINNT >= 0x0600) // Vista and newer only
- ifIt->second.impl().setRunning(pAddress->ReceiveLinkSpeed > 0 || pAddress->TransmitLinkSpeed > 0);
+ ifIt->second.impl().setRunning(pAddress->ReceiveLinkSpeed > 0 || pAddress->TransmitLinkSpeed > 0);
#endif
- ifIt->second.impl().setType(fromNative(pAddress->IfType));
- if (pAddress->PhysicalAddressLength)
- ifIt->second.impl().setMACAddress(pAddress->PhysicalAddress, pAddress->PhysicalAddressLength);
+ ifIt->second.impl().setType(fromNative(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)
+ for (PIP_ADAPTER_UNICAST_ADDRESS pUniAddr = pAddress->FirstUnicastAddress;
+ pUniAddr;
+ pUniAddr = pUniAddr->Next)
+ {
+ address = IPAddress(pUniAddr->Address);
+ ADDRESS_FAMILY family = pUniAddr->Address.lpSockaddr->sa_family;
+ switch (family)
{
- address = IPAddress(pUniAddr->Address);
- ADDRESS_FAMILY family = pUniAddr->Address.lpSockaddr->sa_family;
- switch (family)
- {
- case AF_INET:
+ case AF_INET:
+ {
+ // Windows lists broadcast address on localhost
+ bool hasBroadcast = (pAddress->IfType == IF_TYPE_ETHERNET_CSMACD) || (pAddress->IfType == IF_TYPE_SOFTWARE_LOOPBACK);
+ if (hasBroadcast)
{
- // Windows lists broadcast address on localhost
- bool hasBroadcast = (pAddress->IfType == IF_TYPE_ETHERNET_CSMACD) || (pAddress->IfType == IF_TYPE_SOFTWARE_LOOPBACK);
- if (hasBroadcast)
- {
- // On Windows, a valid broadcast address will be all 1's (== address | ~subnetMask); additionaly, on pre-Vista versions of
- // OS, master address structure does not contain member for prefix length; we go an extra mile here in order to make sure
- // we reflect the actual values held by system and protect against misconfiguration (e.g. bad DHCP config entry)
+ // On Windows, a valid broadcast address will be all 1's (== address | ~subnetMask); additionaly, on pre-Vista versions of
+ // OS, master address structure does not contain member for prefix length; we go an extra mile here in order to make sure
+ // we reflect the actual values held by system and protect against misconfiguration (e.g. bad DHCP config entry)
#if (_WIN32_WINNT >= 0x0600) // Vista and newer
- UINT8 prefixLength = pUniAddr->OnLinkPrefixLength;
- broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address);
+ UINT8 prefixLength = pUniAddr->OnLinkPrefixLength;
+ broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address);
#else
- ULONG prefixLength = 0;
- broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address, &prefixLength);
- // if previous call did not do it, make last-ditch attempt for prefix and broadcast
- if (prefixLength == 0 && pAddress->FirstPrefix)
- prefixLength = pAddress->FirstPrefix->Length;
- poco_assert (prefixLength <= 32);
- if (broadcastAddress.isWildcard())
- {
- IPAddress mask ((unsigned) prefixLength, IPAddress::IPv4);
- IPAddress host(mask & address);
- broadcastAddress = host | ~mask;
- }
-#endif
- subnetMask = prefixLength ? IPAddress(prefixLength, IPAddress::IPv4) : IPAddress();
- ifIt->second.addAddress(address, subnetMask, broadcastAddress);
+ ULONG prefixLength = 0;
+ broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address, &prefixLength);
+ // if previous call did not do it, make last-ditch attempt for prefix and broadcast
+ if (prefixLength == 0 && pAddress->FirstPrefix)
+ prefixLength = pAddress->FirstPrefix->Length;
+ poco_assert (prefixLength <= 32);
+ if (broadcastAddress.isWildcard())
+ {
+ IPAddress mask ((unsigned) prefixLength, IPAddress::IPv4);
+ IPAddress host(mask & address);
+ broadcastAddress = host | ~mask;
}
- else
- ifIt->second.addAddress(address);
- } break;
-#if defined(POCO_HAVE_IPv6)
- case AF_INET6:
+#endif
+ subnetMask = prefixLength ? IPAddress(prefixLength, IPAddress::IPv4) : IPAddress();
+ ifIt->second.addAddress(address, subnetMask, broadcastAddress);
+ }
+ else
ifIt->second.addAddress(address);
- break;
+ } break;
+#if defined(POCO_HAVE_IPv6)
+ case AF_INET6:
+ ifIt->second.addAddress(address);
+ break;
#endif
- } // switch family
- } // for addresses
- } // if ipOnly/upOnly
+ } // switch family
+ } // for addresses
} // for adapters
return result;
}
@@ -1162,12 +1172,11 @@ void setInterfaceParams(struct ifaddrs* iface, NetworkInterfaceImpl& impl)
} // namespace
-NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly)
+NetworkInterface::Map NetworkInterface::full()
{
FastMutex::ScopedLock lock(_mutex);
Map result;
unsigned ifIndex = 0;
- NetworkInterface intf;
Map::iterator ifIt;
struct ifaddrs* ifaces = 0;
@@ -1190,22 +1199,18 @@ NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly)
case AF_LINK:
{
struct sockaddr_dl* sdl = (struct sockaddr_dl*) currIface->ifa_addr;
+ std::string name(currIface->ifa_name);
ifIndex = sdl->sdl_index;
- intf = NetworkInterface(ifIndex);
+ NetworkInterface intf(name, name, ifIndex);
setInterfaceParams(currIface, intf.impl());
- if ((result.find(ifIndex) == result.end()) && ((upOnly && intf.isUp()) || !upOnly) && !ipOnly)
- ifIt = result.insert(Map::value_type(ifIndex, intf)).first;
- break;
+ result.insert(Map::value_type(ifIndex, intf));
+ continue;
}
#endif
case AF_INET:
ifIndex = if_nametoindex(currIface->ifa_name);
ifIt = result.find(ifIndex);
- intf = NetworkInterface(ifIndex);
- setInterfaceParams(currIface, intf.impl());
- if ((ifIt == result.end()) && ((upOnly && intf.isUp()) || !upOnly))
- ifIt = result.insert(Map::value_type(ifIndex, intf)).first;
-
+
address = IPAddress(*(currIface->ifa_addr));
if (( currIface->ifa_flags & IFF_LOOPBACK ) == 0 && currIface->ifa_netmask)
@@ -1222,11 +1227,7 @@ NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly)
case AF_INET6:
ifIndex = if_nametoindex(currIface->ifa_name);
ifIt = result.find(ifIndex);
- intf = NetworkInterface(ifIndex);
- setInterfaceParams(currIface, intf.impl());
- if ((ifIt == result.end()) && ((upOnly && intf.isUp()) || !upOnly))
- ifIt = result.insert(Map::value_type(ifIndex, intf)).first;
-
+
address = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(currIface->ifa_addr)->sin6_addr,
sizeof(struct in6_addr), ifIndex);
subnetMask = IPAddress(*(currIface->ifa_netmask));
@@ -1236,19 +1237,8 @@ NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly)
default:
continue;
}
-
- if (family == AF_INET
-#ifdef POCO_HAVE_IPv6
- || family == AF_INET6
-#endif
- )
- {
- if ((upOnly && intf.isUp()) || !upOnly)
- {
- if ((ifIt = result.find(ifIndex)) != result.end())
- ifIt->second.addAddress(address, subnetMask, broadcastAddress);
- }
- }
+
+ ifIt->second.addAddress(address, subnetMask, broadcastAddress);
}
}
catch (...)
@@ -1314,12 +1304,11 @@ void setInterfaceParams(struct ifaddrs* iface, NetworkInterfaceImpl& impl)
}
-NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly)
+NetworkInterface::Map NetworkInterface::full()
{
FastMutex::ScopedLock lock(_mutex);
Map result;
unsigned ifIndex = 0;
- NetworkInterface intf;
Map::iterator ifIt;
struct ifaddrs* ifaces = 0;
@@ -1341,23 +1330,18 @@ NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly)
case AF_PACKET:
{
struct sockaddr_ll* sll = (struct sockaddr_ll*)iface->ifa_addr;
+ std::string name(iface->ifa_name);
ifIndex = sll->sll_ifindex;
- intf = NetworkInterface(ifIndex);
+ NetworkInterface intf(name, name, ifIndex);
setInterfaceParams(iface, intf.impl());
-
- if ((result.find(ifIndex) == result.end()) && ((upOnly && intf.isUp()) || !upOnly) && !ipOnly)
- ifIt = result.insert(Map::value_type(ifIndex, intf)).first;
-
- break;
+
+ result.insert(Map::value_type(ifIndex, intf));
+
+ continue;
}
case AF_INET:
ifIndex = if_nametoindex(iface->ifa_name);
ifIt = result.find(ifIndex);
- intf = NetworkInterface(ifIndex);
- setInterfaceParams(iface, intf.impl());
-
- if ((ifIt == result.end()) && ((upOnly && intf.isUp()) || !upOnly))
- ifIt = result.insert(Map::value_type(ifIndex, intf)).first;
address = IPAddress(*(iface->ifa_addr));
subnetMask = IPAddress(*(iface->ifa_netmask));
@@ -1374,35 +1358,18 @@ NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly)
case AF_INET6:
ifIndex = if_nametoindex(iface->ifa_name);
ifIt = result.find(ifIndex);
- intf = NetworkInterface(ifIndex);
- setInterfaceParams(iface, intf.impl());
-
- if ((ifIt == result.end()) && ((upOnly && intf.isUp()) || !upOnly))
- result.insert(Map::value_type(ifIndex, intf)).first;
address = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(iface->ifa_addr)->sin6_addr, sizeof(struct in6_addr), ifIndex);
subnetMask = IPAddress(*(iface->ifa_netmask));
broadcastAddress = IPAddress();
-
+
break;
#endif
default:
continue;
}
- if (family == AF_INET
-#ifdef POCO_HAVE_IPv6
- || family == AF_INET6
-#endif
- )
- {
- intf = NetworkInterface(std::string(iface->ifa_name), address, subnetMask, broadcastAddress, ifIndex);
- if ((upOnly && intf.isUp()) || !upOnly)
- {
- if ((ifIt = result.find(ifIndex)) != result.end())
- ifIt->second.addAddress(address, subnetMask, broadcastAddress);
- }
- }
+ ifIt->second.addAddress(address, subnetMask, broadcastAddress);
} // for interface
}
catch (...)

0 comments on commit b79e855

Please sign in to comment.