Skip to content

Commit 255abe7

Browse files
authored
Revert "Revert "by default use the default egress interface (#44)" (#49)" (#50)
This reverts commit 0d871e8.
1 parent 0d871e8 commit 255abe7

File tree

3 files changed

+138
-5
lines changed

3 files changed

+138
-5
lines changed

src/main/java/com/fasterxml/uuid/EthernetAddress.java

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@
1616
package com.fasterxml.uuid;
1717

1818
import java.io.Serializable;
19+
import java.net.DatagramSocket;
20+
import java.net.InetAddress;
21+
import java.net.InetSocketAddress;
1922
import java.net.NetworkInterface;
23+
import java.net.SocketException;
2024
import java.security.SecureRandom;
2125
import java.util.Enumeration;
2226
import java.util.Random;
@@ -271,18 +275,81 @@ public static EthernetAddress fromInterface()
271275
while (en.hasMoreElements()) {
272276
NetworkInterface nint = en.nextElement();
273277
if (!nint.isLoopback()) {
274-
byte[] data = nint.getHardwareAddress();
275-
if (data != null && data.length == 6) {
276-
return new EthernetAddress(data);
277-
}
278+
return fromInterface(nint);
278279
}
279280
}
280281
} catch (java.net.SocketException e) {
281282
// fine, let's take is as signal of not having any interfaces
282283
}
283284
return null;
284285
}
285-
286+
287+
/**
288+
* A factory method to return the ethernet address of a specified network interface.
289+
*/
290+
public static EthernetAddress fromInterface(NetworkInterface nint)
291+
{
292+
try {
293+
byte[] data = nint.getHardwareAddress();
294+
if (data != null && data.length == 6) {
295+
return new EthernetAddress(data);
296+
}
297+
} catch (SocketException e) {
298+
// could not get address
299+
}
300+
return null;
301+
}
302+
303+
/**
304+
* A factory method that will try to determine the ethernet address of
305+
* the network interface that connects to the default network gateway.
306+
* To do this it will try to open a connection to one of the root DNS
307+
* servers, or barring that, to adresss 1.1.1.1, or finally if that also
308+
* fails then to IPv6 address "1::1". If a connection can be opened then
309+
* the interface through which that connection is routed is determined
310+
* to be the default egress interface, and the corresponding address of
311+
* that interface will be returned. If all attempts are unsuccessful,
312+
* null will be returned.
313+
*/
314+
public static EthernetAddress fromEgressInterface()
315+
{
316+
String roots = "abcdefghijklm";
317+
int index = new Random().nextInt(roots.length());
318+
String name = roots.charAt(index) + ".root-servers.net";
319+
InetSocketAddress externalAddress = new InetSocketAddress(name, 0);
320+
if (externalAddress.isUnresolved()) {
321+
externalAddress = new InetSocketAddress("1.1.1.1", 0);
322+
}
323+
EthernetAddress ifAddr = fromEgressInterface(externalAddress);
324+
if (ifAddr == null) {
325+
return fromEgressInterface(new InetSocketAddress("1::1", 0));
326+
} else {
327+
return ifAddr;
328+
}
329+
}
330+
331+
/**
332+
* A factory method to return the address of the interface used to route
333+
* traffic to the specified address.
334+
*/
335+
public static EthernetAddress fromEgressInterface(InetSocketAddress externalSocketAddress)
336+
{
337+
DatagramSocket socket = null;
338+
try {
339+
socket = new DatagramSocket();
340+
socket.connect(externalSocketAddress);
341+
InetAddress localAddress = socket.getLocalAddress();
342+
NetworkInterface egressIf = NetworkInterface.getByInetAddress(localAddress);
343+
return fromInterface(egressIf);
344+
} catch (SocketException e) {
345+
return null;
346+
} finally {
347+
if (socket != null) {
348+
socket.close();
349+
}
350+
}
351+
}
352+
286353
/**
287354
* Factory method that can be used to construct a random multicast
288355
* address; to be used in cases where there is no "real" ethernet

src/main/java/com/fasterxml/uuid/Generators.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ public class Generators
4040
* synchronization but no external file-based syncing.
4141
*/
4242
protected static UUIDTimer _sharedTimer;
43+
44+
/**
45+
* The default egress network interface.
46+
*/
47+
protected static EthernetAddress _egressIfAddr = null;
4348

4449
// // Random-based generation
4550

@@ -116,6 +121,18 @@ public static NameBasedGenerator nameBasedGenerator(UUID namespace, MessageDiges
116121

117122
// // Time+location-based generation
118123

124+
/**
125+
* Factory method for constructing UUID generator that generates UUID using variant 1
126+
* (time+location based). This method will use the ethernet address of the interface
127+
* that routes to the default gateway. For most simple and common networking configurations
128+
* this will be the most appropriate address to use. The default interface is determined
129+
* by the calling {@link EthernetAddress#fromEgressInterface()}.
130+
*/
131+
public static TimeBasedGenerator egressTimeBasedGenerator()
132+
{
133+
return timeBasedGenerator(egressInterfaceAddress());
134+
}
135+
119136
/**
120137
* Factory method for constructing UUID generator that generates UUID using
121138
* variant 1 (time+location based).
@@ -238,4 +255,12 @@ private static synchronized UUIDTimer sharedTimer()
238255
}
239256
return _sharedTimer;
240257
}
258+
259+
private static synchronized EthernetAddress egressInterfaceAddress()
260+
{
261+
if (_egressIfAddr == null) {
262+
_egressIfAddr = EthernetAddress.fromEgressInterface();
263+
}
264+
return _egressIfAddr;
265+
}
241266
}

src/test/java/com/fasterxml/uuid/EthernetAddressTest.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
package com.fasterxml.uuid;
1919

20+
import com.fasterxml.uuid.impl.TimeBasedGenerator;
21+
import java.net.InetSocketAddress;
2022
import junit.framework.Test;
2123
import junit.framework.TestCase;
2224
import junit.framework.TestSuite;
@@ -1307,6 +1309,45 @@ public void testFromInterface() throws Exception
13071309
assertNotNull(addr.toString());
13081310
}
13091311

1312+
public void testFromEgressInterfaceRoot() throws Exception
1313+
{
1314+
InetSocketAddress extAddr = new InetSocketAddress("a.root-servers.net", 0);
1315+
EthernetAddress ifAddr = EthernetAddress.fromEgressInterface(extAddr);
1316+
assertNotNull(ifAddr);
1317+
assertNotNull(ifAddr.toString());
1318+
}
1319+
1320+
public void testFromEgressInterfaceIp4() throws Exception
1321+
{
1322+
InetSocketAddress extAddr = new InetSocketAddress("1.1.1.1", 0);
1323+
EthernetAddress ifAddr = EthernetAddress.fromEgressInterface(extAddr);
1324+
assertNotNull(ifAddr);
1325+
assertNotNull(ifAddr.toString());
1326+
}
1327+
1328+
public void testFromEgressInterfaceIp6() throws Exception
1329+
{
1330+
InetSocketAddress extAddr = new InetSocketAddress("1::1", 0);
1331+
EthernetAddress ifAddr = EthernetAddress.fromEgressInterface(extAddr);
1332+
assertNotNull(ifAddr);
1333+
assertNotNull(ifAddr.toString());
1334+
}
1335+
1336+
public void testFromEgressInterface() throws Exception
1337+
{
1338+
EthernetAddress ifAddr = EthernetAddress.fromEgressInterface();
1339+
assertNotNull(ifAddr);
1340+
assertNotNull(ifAddr.toString());
1341+
}
1342+
1343+
public void testDefaultTimeBasedGenerator()
1344+
{
1345+
TimeBasedGenerator generator = Generators.egressTimeBasedGenerator();
1346+
EthernetAddress ifAddr = generator.getEthernetAddress();
1347+
assertNotNull(ifAddr);
1348+
assertNotNull(ifAddr.toString());
1349+
}
1350+
13101351
public void testBogus() throws Exception
13111352
{
13121353
// First, two using pseudo-random; verify they are different

0 commit comments

Comments
 (0)