Skip to content

Commit a585a1d

Browse files
authored
Fix incorrect hostname on non-managed devices (#2203)
I have all sorts of weird adapters from npcap and Hyper-V that don't have MAC addresses, so I'm simplifying the logic down so that it always tries to find _any_ adapter with a MAC address, but attempts to see if it can find what adapter is in use right now and use the MAC address from that. This also unpublishes old MAC address topics, which wasn't done before.
1 parent 9490c2f commit a585a1d

File tree

2 files changed

+54
-27
lines changed

2 files changed

+54
-27
lines changed

photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NetworkTablesManager.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,14 +253,22 @@ private void checkHostnameAndCameraNames() {
253253
String mac = NetworkUtils.getMacAddress();
254254
if (!mac.equals(currentMacAddress)) {
255255
logger.debug("MAC address changed! New MAC address is " + mac + ", was " + currentMacAddress);
256+
kCoprocTable.getSubTable(currentMacAddress).getEntry("hostname").unpublish();
257+
kCoprocTable.getSubTable(currentMacAddress).getEntry("cameraNames").unpublish();
256258
currentMacAddress = mac;
257259
}
258260
if (mac.isEmpty()) {
259261
logger.error("Cannot check hostname and camera names, MAC address is not set!");
260262
return;
261263
}
262264

263-
String hostname = ConfigManager.getInstance().getConfig().getNetworkConfig().hostname;
265+
var config = ConfigManager.getInstance().getConfig();
266+
String hostname;
267+
if (config.getNetworkConfig().shouldManage) {
268+
hostname = config.getNetworkConfig().hostname;
269+
} else {
270+
hostname = CameraServerJNI.getHostname();
271+
}
264272
if (hostname == null || hostname.isEmpty()) {
265273
logger.error("Cannot check hostname and camera names, hostname is not set!");
266274
return;

photon-core/src/main/java/org/photonvision/common/networking/NetworkUtils.java

Lines changed: 45 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717

1818
package org.photonvision.common.networking;
1919

20+
import edu.wpi.first.networktables.NetworkTableInstance;
2021
import java.io.IOException;
22+
import java.net.InetAddress;
2123
import java.net.NetworkInterface;
2224
import java.util.ArrayList;
2325
import java.util.List;
@@ -218,40 +220,57 @@ public static String getIPAddresses(String iFaceName) {
218220
return String.join(", ", addresses);
219221
}
220222

223+
/**
224+
* Gets a MAC address of a network interface. On devices where networking is managed by
225+
* PhotonVision, this will return the MAC address of the configured interface. Otherwise, this
226+
* will attempt to search for the network interface in current use and use that interface's MAC
227+
* address, and if that fails, it will return a MAC address from the first network interface with
228+
* a MAC address, as sorted by {@link NetworkInterface#networkInterfaces()}.
229+
*
230+
* @return The MAC address.
231+
*/
221232
public static String getMacAddress() {
222233
var config = ConfigManager.getInstance().getConfig().getNetworkConfig();
223-
if (config.networkManagerIface == null || config.networkManagerIface.isBlank()) {
224-
// This is a silly heuristic to find a network interface that PV might be using. It looks like
225-
// it works pretty well, but Hyper-V adapters still show up in the list. But we're using MAC
226-
// address as a semi-unique identifier, not as a source of truth, so this should be fine.
227-
// Hyper-V adapters seem to show up near the end of the list anyways, so it's super likely
228-
// we'll find the right adapter anyways
229-
try {
230-
for (var iface : NetworkInterface.networkInterfaces().toList()) {
231-
if (iface.isUp() && !iface.isVirtual() && !iface.isLoopback()) {
232-
byte[] mac = iface.getHardwareAddress();
233-
if (mac == null) {
234-
logger.error("No MAC address found for " + iface.getDisplayName());
235-
}
234+
try {
235+
// Not managed? See if we're connected to a network. General assumption is one interface in
236+
// use at a time
237+
if (config.networkManagerIface == null || config.networkManagerIface.isBlank()) {
238+
// Use NT client IP address to find the interface in use
239+
if (!config.runNTServer) {
240+
var conn = NetworkTableInstance.getDefault().getConnections();
241+
if (conn.length > 0 && !conn[0].remote_ip.equals("127.0.0.1")) {
242+
var addr = InetAddress.getByName(conn[0].remote_ip);
243+
return formatMacAddress(NetworkInterface.getByInetAddress(addr).getHardwareAddress());
244+
}
245+
}
246+
// Connected to a localhost server or we are the server? Try resolving ourselves. Only
247+
// returns a localhost address when there's no other interface available on Windows, but
248+
// like to return a localhost address on Linux
249+
var localIface = NetworkInterface.getByInetAddress(InetAddress.getLocalHost());
250+
if (localIface != null) {
251+
byte[] mac = localIface.getHardwareAddress();
252+
if (mac != null) {
236253
return formatMacAddress(mac);
237254
}
238255
}
239-
} catch (Exception e) {
240-
logger.error("Error getting MAC address:", e);
241-
}
242-
return "";
243-
}
244-
try {
245-
byte[] mac = NetworkInterface.getByName(config.networkManagerIface).getHardwareAddress();
246-
if (mac == null) {
247-
logger.error("No MAC address found for " + config.networkManagerIface);
248-
return "";
256+
// Fine. Just find something with a MAC address
257+
for (var iface : NetworkInterface.networkInterfaces().toList()) {
258+
if (iface.isUp() && iface.getHardwareAddress() != null) {
259+
return formatMacAddress(iface.getHardwareAddress());
260+
}
261+
}
262+
} else { // Managed? We should have a working interface available
263+
byte[] mac = NetworkInterface.getByName(config.networkManagerIface).getHardwareAddress();
264+
if (mac != null) {
265+
return formatMacAddress(mac);
266+
} else {
267+
logger.error("No MAC address found for " + config.networkManagerIface);
268+
}
249269
}
250-
return formatMacAddress(mac);
251270
} catch (Exception e) {
252-
logger.error("Error getting MAC address for " + config.networkManagerIface, e);
253-
return "";
271+
logger.error("Error getting MAC address", e);
254272
}
273+
return "";
255274
}
256275

257276
private static String formatMacAddress(byte[] mac) {

0 commit comments

Comments
 (0)