X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.api.uuid%2Fsrc%2Forg%2Fargeo%2Fapi%2Fuuid%2FConcurrentUuidFactory.java;h=4ad2290b9c52d1ee9cb80efd240920747d7d8fa0;hb=d3d0be6695c92a35a46106e955d41ac73c82b6c0;hp=05b2f05c6b62345e0160363c7129983301d32ade;hpb=e846ef84146b66ae543c29c5f17b2991ff0f5973;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.api.uuid/src/org/argeo/api/uuid/ConcurrentUuidFactory.java b/org.argeo.api.uuid/src/org/argeo/api/uuid/ConcurrentUuidFactory.java index 05b2f05c6..4ad2290b9 100644 --- a/org.argeo.api.uuid/src/org/argeo/api/uuid/ConcurrentUuidFactory.java +++ b/org.argeo.api.uuid/src/org/argeo/api/uuid/ConcurrentUuidFactory.java @@ -1,12 +1,21 @@ package org.argeo.api.uuid; import static java.lang.System.Logger.Level.DEBUG; +import static java.lang.System.Logger.Level.INFO; import static java.lang.System.Logger.Level.WARNING; import java.lang.System.Logger; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.InterfaceAddress; +import java.net.NetworkInterface; +import java.net.SocketException; import java.security.DrbgParameters; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; +import java.util.BitSet; +import java.util.Enumeration; import java.util.Objects; /** @@ -18,8 +27,6 @@ import java.util.Objects; public class ConcurrentUuidFactory extends AbstractAsyncUuidFactory { private final static Logger logger = System.getLogger(ConcurrentUuidFactory.class.getName()); -// private byte[] defaultNodeId; - private Long nodeIdBase; public ConcurrentUuidFactory(byte[] nodeId, int offset) { @@ -29,10 +36,14 @@ public class ConcurrentUuidFactory extends AbstractAsyncUuidFactory { byte[] defaultNodeId = toNodeIdBytes(nodeId, offset); nodeIdBase = NodeIdSupplier.toNodeIdBase(defaultNodeId); setNodeIdSupplier(() -> nodeIdBase); + assert newTimeUUID().node() == BitSet.valueOf(defaultNodeId).toLongArray()[0]; } - protected ConcurrentUuidFactory() { - + public ConcurrentUuidFactory() { + byte[] defaultNodeId = getIpBytes(); + nodeIdBase = NodeIdSupplier.toNodeIdBase(defaultNodeId); + setNodeIdSupplier(() -> nodeIdBase); + assert newTimeUUID().node() == BitSet.valueOf(defaultNodeId).toLongArray()[0]; } @Override @@ -53,12 +64,61 @@ public class ConcurrentUuidFactory extends AbstractAsyncUuidFactory { return secureRandom; } - /* - * TIME-BASED (version 1) - */ -// -// @Override -// public UUID newTimeUUID() { -// return newTimeUUID(timeUuidState.useTimestamp(), timeUuidState.getClockSequence(), defaultNodeId, 0); -// } -} + /** Returns an SHA1 digest of one of the IP addresses. */ + protected byte[] getIpBytes() { + Enumeration netInterfaces = null; + try { + netInterfaces = NetworkInterface.getNetworkInterfaces(); + } catch (SocketException e) { + throw new IllegalStateException(e); + } + if (netInterfaces == null) + throw new IllegalStateException("No interfaces"); + + InetAddress selectedIpv6 = null; + InetAddress selectedIpv4 = null; + netInterfaces: while (netInterfaces.hasMoreElements()) { + NetworkInterface netInterface = netInterfaces.nextElement(); + byte[] hardwareAddress = null; + try { + hardwareAddress = netInterface.getHardwareAddress(); + if (hardwareAddress != null) { + // first IPv6 + addr: for (InterfaceAddress addr : netInterface.getInterfaceAddresses()) { + InetAddress ip = addr.getAddress(); + if (ip instanceof Inet6Address) { + Inet6Address ipv6 = (Inet6Address) ip; + if (ipv6.isAnyLocalAddress() || ipv6.isLinkLocalAddress() || ipv6.isLoopbackAddress()) + continue addr; + selectedIpv6 = ipv6; + break netInterfaces; + } + + } + // then IPv4 + addr: for (InterfaceAddress addr : netInterface.getInterfaceAddresses()) { + InetAddress ip = addr.getAddress(); + if (ip instanceof Inet4Address) { + Inet4Address ipv4 = (Inet4Address) ip; + if (ipv4.isAnyLocalAddress() || ipv4.isLinkLocalAddress() || ipv4.isLoopbackAddress()) + continue addr; + selectedIpv4 = ipv4; + } + + } + } + } catch (SocketException e) { + throw new IllegalStateException(e); + } + } + InetAddress selectedIp = selectedIpv6 != null ? selectedIpv6 : selectedIpv4; + if (selectedIp == null) + throw new IllegalStateException("No IP address found"); + byte[] digest = sha1(selectedIp.getAddress()); + logger.log(INFO, "Use IP " + selectedIp + " hashed as " + toHexString(digest) + " as node id"); + byte[] nodeId = toNodeIdBytes(digest, 0); + // marks that this is not based on MAC address + forceToNoMacAddress(nodeId, 0); + return nodeId; + } +} \ No newline at end of file