Skip to content

Commit

Permalink
[Network] fix oom bug (openhab#4827)
Browse files Browse the repository at this point in the history
fix oom bug (openhab#4827)

Signed-off-by: Jan N. Klug <[email protected]>
  • Loading branch information
J-N-K authored and jannegpriv committed Mar 3, 2019
1 parent a465a89 commit 77659e8
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Import-Package:
org.eclipse.smarthome.config.discovery,
org.eclipse.smarthome.core.cache,
org.eclipse.smarthome.core.library.types,
org.eclipse.smarthome.core.net,
org.eclipse.smarthome.core.thing,
org.eclipse.smarthome.core.thing.binding,
org.eclipse.smarthome.core.types,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
import java.net.ConnectException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.NoRouteToHostException;
import java.net.PortUnreachableException;
Expand All @@ -30,16 +30,20 @@
import java.net.SocketTimeoutException;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.SystemUtils;
import org.apache.commons.net.util.SubnetUtils;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.core.net.CidrAddress;
import org.eclipse.smarthome.core.net.NetUtil;
import org.eclipse.smarthome.io.net.exec.ExecUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Network utility functions for pinging and for determining all interfaces and assigned IP addresses.
Expand All @@ -48,45 +52,17 @@
*/
@NonNullByDefault
public class NetworkUtils {
private final Logger logger = LoggerFactory.getLogger(NetworkUtils.class);

/**
* Gets every IPv4 Address on each Interface except the loopback
* The Address format is ip/subnet
*
* @return The collected IPv4 Addresses
*/
public Set<String> getInterfaceIPs() {
Set<String> interfaceIPs = new HashSet<>();

Enumeration<NetworkInterface> interfaces;
try {
interfaces = NetworkInterface.getNetworkInterfaces();
} catch (SocketException ignored) {
// If we are not allowed to enumerate, we return an empty result set.
return interfaceIPs;
}

// For each interface ...
for (Enumeration<NetworkInterface> en = interfaces; en.hasMoreElements();) {
NetworkInterface networkInterface = en.nextElement();
boolean isLoopback = true;
try {
isLoopback = networkInterface.isLoopback();
} catch (SocketException ignored) {
}
if (!isLoopback) {
// .. and for each address ...
for (Iterator<InterfaceAddress> it = networkInterface.getInterfaceAddresses().iterator(); it
.hasNext();) {

// ... get IP and Subnet
InterfaceAddress interfaceAddress = it.next();
interfaceIPs.add(interfaceAddress.getAddress().getHostAddress() + "/"
+ interfaceAddress.getNetworkPrefixLength());
}
}
}

return interfaceIPs;
public Set<CidrAddress> getInterfaceIPs() {
return NetUtil.getAllInterfaceAddresses().stream().filter(a -> a.getAddress() instanceof Inet4Address)
.collect(Collectors.toSet());
}

/**
Expand Down Expand Up @@ -129,22 +105,38 @@ public Set<String> getNetworkIPs(int maximumPerInterface) {
* @param maximumPerInterface The maximum of IP addresses per interface or 0 to get all.
* @return Every single IP which can be assigned on the Networks the computer is connected to
*/
public Set<String> getNetworkIPs(Set<String> interfaceIPs, int maximumPerInterface) {
public Set<String> getNetworkIPs(Set<CidrAddress> interfaceIPs, int maximumPerInterface) {
LinkedHashSet<String> networkIPs = new LinkedHashSet<>();

for (String string : interfaceIPs) {
try {
// gets every ip which can be assigned on the given network
SubnetUtils utils = new SubnetUtils(string);
String[] addresses = utils.getInfo().getAllAddresses();
int len = addresses.length;
if (maximumPerInterface != 0 && maximumPerInterface < len) {
len = maximumPerInterface;
}
for (int i = 0; i < len; i++) {
networkIPs.add(addresses[i]);
}
} catch (Exception ex) {
short minCidrPrefixLength = 8; // historic Class A network, addresses = 16777214
if (maximumPerInterface != 0) {
// calculate minimum CIDR prefix length from maximumPerInterface
// (equals leading unset bits (Integer has 32 bits)
minCidrPrefixLength = (short) Integer.numberOfLeadingZeros(maximumPerInterface);
if (Integer.bitCount(maximumPerInterface) == 1) {
// if only the highest is set, decrease prefix by 1 to cover all addresses
minCidrPrefixLength--;
}
}
logger.trace("set minCidrPrefixLength to {}, maximumPerInterface is {}", minCidrPrefixLength,
maximumPerInterface);

for (CidrAddress cidrNotation : interfaceIPs) {
if (cidrNotation.getPrefix() < minCidrPrefixLength) {
logger.info(
"CIDR prefix is smaller than /{} on interface with address {}, truncating to /{}, some addresses might be lost",
minCidrPrefixLength, cidrNotation, minCidrPrefixLength);
cidrNotation = new CidrAddress(cidrNotation.getAddress(), minCidrPrefixLength);
}

SubnetUtils utils = new SubnetUtils(cidrNotation.toString());
String[] addresses = utils.getInfo().getAllAddresses();
int len = addresses.length;
if (maximumPerInterface != 0 && maximumPerInterface < len) {
len = maximumPerInterface;
}
for (int i = 0; i < len; i++) {
networkIPs.add(addresses[i]);
}
}

Expand Down

0 comments on commit 77659e8

Please sign in to comment.