Skip to content

Commit c2606e7

Browse files
committed
Improving mDns service dispatch
1 parent c482f9c commit c2606e7

2 files changed

Lines changed: 51 additions & 4 deletions

File tree

common/src/main/java/xyz/gianlu/librespot/common/Utils.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,8 @@ public static String bytesToHex(@NotNull ByteString bytes) {
181181

182182
@NotNull
183183
public static String bytesToHex(byte[] bytes) {
184+
if (bytes == null) return "";
185+
184186
char[] hexChars = new char[bytes.length * 2];
185187
for (int j = 0; j < bytes.length; j++) {
186188
int v = bytes[j] & 0xFF;

core/src/main/java/xyz/gianlu/librespot/core/ZeroconfServer.java

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,26 @@ public class ZeroconfServer implements Closeable {
3838
private static final byte[] EOL = new byte[]{'\r', '\n'};
3939
private static final JsonObject DEFAULT_GET_INFO_FIELDS = new JsonObject();
4040
private static final JsonObject DEFAULT_SUCCESSFUL_ADD_USER = new JsonObject();
41+
private static final byte[][] VIRTUAL_INTERFACES = new byte[][]{
42+
new byte[]{(byte) 0x00, (byte) 0x0F, (byte) 0x4B}, // Virtual Iron Software, Inc.
43+
new byte[]{(byte) 0x00, (byte) 0x13, (byte) 0x07}, // Paravirtual Corporation
44+
new byte[]{(byte) 0x00, (byte) 0x13, (byte) 0xBE}, // Virtual Conexions
45+
new byte[]{(byte) 0x00, (byte) 0x21, (byte) 0xF6}, // Virtual Iron Software
46+
new byte[]{(byte) 0x00, (byte) 0x24, (byte) 0x0B}, // Virtual Computer Inc.
47+
new byte[]{(byte) 0x00, (byte) 0xA0, (byte) 0xB1}, // First Virtual Corporation
48+
new byte[]{(byte) 0x00, (byte) 0xE0, (byte) 0xC8}, // Virtual access, ltd.
49+
new byte[]{(byte) 0x54, (byte) 0x52, (byte) 0x00}, // Linux kernel virtual machine (kvm)
50+
new byte[]{(byte) 0x00, (byte) 0x21, (byte) 0xF6}, // Oracle Corporation
51+
new byte[]{(byte) 0x18, (byte) 0x92, (byte) 0x2C}, // Virtual Instruments
52+
new byte[]{(byte) 0x3C, (byte) 0xF3, (byte) 0x92}, // VirtualTek. Co. Ltd.
53+
new byte[]{(byte) 0x00, (byte) 0x05, (byte) 0x69}, // VMWare 1
54+
new byte[]{(byte) 0x00, (byte) 0x0C, (byte) 0x29}, // VMWare 2
55+
new byte[]{(byte) 0x00, (byte) 0x50, (byte) 0x56}, // VMWare 3
56+
new byte[]{(byte) 0x00, (byte) 0x1C, (byte) 0x42}, // Parallels
57+
new byte[]{(byte) 0x00, (byte) 0x03, (byte) 0xFF}, // Microsoft Virtual PC
58+
new byte[]{(byte) 0x00, (byte) 0x16, (byte) 0x3E}, // Red Hat Xen, Oracle VM, Xen Source, Novell Xen
59+
new byte[]{(byte) 0x08, (byte) 0x00, (byte) 0x27}, // VirtualBox
60+
};
4161

4262
static {
4363
DEFAULT_GET_INFO_FIELDS.addProperty("status", 101);
@@ -87,7 +107,7 @@ private ZeroconfServer(Session.Inner inner, Configuration conf) throws IOExcepti
87107

88108
LOGGER.debug("Registering service on " + Arrays.toString(bound));
89109

90-
ServiceInstance service = new ServiceInstance(new ServiceName("librespot._spotify-connect._tcp.local."), 0, 0, port, Name.fromString("local."), bound, "VERSION=1.0", "CPath=/");
110+
ServiceInstance service = new ServiceInstance(new ServiceName("librespot-java._spotify-connect._tcp.local."), 0, 0, port, Name.fromString("local."), bound, "VERSION=1.0", "CPath=/");
91111
spotifyConnectService = mDnsService.register(service);
92112
if (spotifyConnectService == null)
93113
throw new IOException("Failed registering SpotifyConnect service!");
@@ -106,10 +126,35 @@ private static void addAddressForInterfaceName(List<InetAddress> list, @NotNull
106126
return;
107127
}
108128

109-
addAddressOfInterface(list, nif);
129+
addAddressOfInterface(list, nif, false);
110130
}
111131

112-
private static void addAddressOfInterface(List<InetAddress> list, @NotNull NetworkInterface nif) {
132+
private static boolean isVirtual(@NotNull NetworkInterface nif) throws SocketException {
133+
byte[] mac = nif.getHardwareAddress();
134+
if (mac == null) return true;
135+
136+
outer:
137+
for (byte[] virtual : VIRTUAL_INTERFACES) {
138+
for (int i = 0; i < Math.min(virtual.length, mac.length); i++) {
139+
if (virtual[i] != mac[i])
140+
continue outer;
141+
}
142+
143+
return true;
144+
}
145+
146+
return false;
147+
}
148+
149+
private static void addAddressOfInterface(List<InetAddress> list, @NotNull NetworkInterface nif, boolean checkVirtual) throws SocketException {
150+
if (nif.isLoopback()) return;
151+
152+
if (isVirtual(nif)) {
153+
if (checkVirtual) return;
154+
else
155+
LOGGER.warn(String.format("Interface %s is suspected to be virtual, mac: %s", nif.getName(), Utils.bytesToHex(nif.getHardwareAddress())));
156+
}
157+
113158
LOGGER.trace(String.format("Adding addresses of %s (displayName: %s)", nif.getName(), nif.getDisplayName()));
114159
Enumeration<InetAddress> ias = nif.getInetAddresses();
115160
while (ias.hasMoreElements())
@@ -120,7 +165,7 @@ private static void addAddressOfInterface(List<InetAddress> list, @NotNull Netwo
120165
private static InetAddress[] getAllInterfacesAddresses() throws SocketException {
121166
List<InetAddress> list = new ArrayList<>();
122167
Enumeration<NetworkInterface> is = NetworkInterface.getNetworkInterfaces();
123-
while (is.hasMoreElements()) addAddressOfInterface(list, is.nextElement());
168+
while (is.hasMoreElements()) addAddressOfInterface(list, is.nextElement(), true);
124169
return list.toArray(new InetAddress[0]);
125170
}
126171

0 commit comments

Comments
 (0)