Skip to content

Commit 8dc6a7f

Browse files
authored
Merge pull request #33 from snekiam/master
Fix for #32 - correctly advertise IP Addresses for multiple network
2 parents d031eb5 + 11fe79b commit 8dc6a7f

7 files changed

Lines changed: 99 additions & 13 deletions

File tree

.travis.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
language: java
22

33
before_install:
4-
- echo $GPG_SECRET_KEYS | base64 --decode | $GPG_EXECUTABLE --import
5-
- echo $GPG_OWNERTRUST | base64 --decode | $GPG_EXECUTABLE --import-ownertrust
4+
- |
5+
if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then
6+
echo $GPG_SECRET_KEYS | base64 --decode | $GPG_EXECUTABLE --import
7+
echo $GPG_OWNERTRUST | base64 --decode | $GPG_EXECUTABLE --import-ownertrust
8+
fi
69
710
install:
811
- mvn install -DskipTests=true -Dgpg.skip -Dmaven.javadoc.skip=true -B -V

conf.properties

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,9 @@ auth.password=
1212
## Spotify authentication blob (BLOB)
1313
auth.blob=
1414
## Cache enabled
15-
cache.enabled=false
15+
cache.enabled=false
16+
# Zeroconf
17+
## Listen on all interfaces (overrides `zeroconf.interfaces`)
18+
zeroconf.listenAll=true
19+
## Listen on this interfaces (comma separated list of names)
20+
zeroconf.interfaces=

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
import org.jetbrains.annotations.Nullable;
44
import xyz.gianlu.librespot.core.AuthConfiguration;
55
import xyz.gianlu.librespot.core.Session;
6+
import xyz.gianlu.librespot.core.ZeroconfAuthenticator;
67
import xyz.gianlu.librespot.player.CacheManager;
78
import xyz.gianlu.librespot.player.Player;
89

910
/**
1011
* @author Gianlu
1112
*/
12-
public abstract class AbsConfiguration implements Player.PlayerConfiguration, CacheManager.CacheConfiguration, AuthConfiguration {
13+
public abstract class AbsConfiguration implements Player.PlayerConfiguration, CacheManager.CacheConfiguration, AuthConfiguration, ZeroconfAuthenticator.Configuration {
1314

1415
@Nullable
1516
public abstract String deviceName();

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,14 @@ public Session.DeviceType deviceType() {
8383
public Strategy strategy() {
8484
return Strategy.ZEROCONF;
8585
}
86+
87+
@Override
88+
public boolean zeroconfListenAll() {
89+
return true;
90+
}
91+
92+
@Override
93+
public @NotNull String[] zeroconfInterfaces() {
94+
return new String[0];
95+
}
8696
}

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,14 @@ private <E extends Enum<E>> E getEnum(@NotNull Class<E> clazz, @NotNull String k
7373
}
7474
}
7575

76+
@NotNull
77+
private String[] getStringArray(@NotNull String key, @NotNull String[] fallback) {
78+
String str = properties.getProperty(key, null);
79+
if (str == null) return fallback;
80+
else if ((str = str.trim()).isEmpty()) return new String[0];
81+
else return Utils.split(str, ',');
82+
}
83+
7684
@Override
7785
public boolean cacheEnabled() {
7886
return getBoolean("cache.enabled", defaults.cacheEnabled());
@@ -133,4 +141,15 @@ public float normalisationPregain() {
133141
public Strategy strategy() {
134142
return getEnum(Strategy.class, "auth.strategy", defaults.strategy());
135143
}
144+
145+
@Override
146+
public boolean zeroconfListenAll() {
147+
return getBoolean("zeroconf.listenAll", defaults.zeroconfListenAll());
148+
}
149+
150+
@NotNull
151+
@Override
152+
public String[] zeroconfInterfaces() {
153+
return getStringArray("zeroconf.interfaces", defaults.zeroconfInterfaces());
154+
}
136155
}

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,9 +405,12 @@ public static class Builder {
405405
private final Inner inner;
406406
private Authentication.LoginCredentials loginCredentials = null;
407407
private AuthConfiguration authConf;
408+
private ZeroconfAuthenticator.Configuration zeroconfConf;
408409

409410
public Builder(@NotNull DeviceType deviceType, @NotNull String deviceName, @NotNull AbsConfiguration configuration) {
410411
this.inner = new Inner(deviceType, deviceName, configuration);
412+
this.authConf = configuration;
413+
this.zeroconfConf = configuration;
411414
}
412415

413416
public Builder(@NotNull AbsConfiguration configuration) {
@@ -421,6 +424,7 @@ public Builder(@NotNull AbsConfiguration configuration) {
421424

422425
this.inner = new Inner(deviceType, deviceName, configuration);
423426
this.authConf = configuration;
427+
this.zeroconfConf = configuration;
424428
}
425429

426430
public Builder facebook() throws IOException {
@@ -433,7 +437,7 @@ public Builder facebook() throws IOException {
433437
}
434438

435439
public Builder zeroconf() throws IOException {
436-
try (ZeroconfAuthenticator authenticator = new ZeroconfAuthenticator(inner)) {
440+
try (ZeroconfAuthenticator authenticator = new ZeroconfAuthenticator(inner, zeroconfConf)) {
437441
loginCredentials = authenticator.lockUntilCredentials();
438442
return this;
439443
} catch (InterruptedException ex) {

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

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,7 @@
2020
import java.io.DataInputStream;
2121
import java.io.IOException;
2222
import java.io.OutputStream;
23-
import java.net.InetAddress;
24-
import java.net.ServerSocket;
25-
import java.net.Socket;
26-
import java.net.URLDecoder;
23+
import java.net.*;
2724
import java.security.GeneralSecurityException;
2825
import java.security.MessageDigest;
2926
import java.util.*;
@@ -65,22 +62,62 @@ public class ZeroconfAuthenticator implements Closeable {
6562
private final Session.Inner session;
6663
private final DiffieHellman keys;
6764

68-
ZeroconfAuthenticator(Session.Inner session) throws IOException {
65+
ZeroconfAuthenticator(Session.Inner session, Configuration conf) throws IOException {
6966
this.session = session;
7067
this.keys = new DiffieHellman(session.random);
7168
this.mDnsService = new MulticastDNSService();
7269

7370
int port = session.random.nextInt((MAX_PORT - MIN_PORT) + 1) + MIN_PORT;
7471
new Thread(this.runner = new HttpRunner(port)).start();
7572

76-
ServiceInstance service = new ServiceInstance(new ServiceName("librespot._spotify-connect._tcp.local."), 0, 0, port, Name.fromString("local."), InetAddress.getAllByName("localhost"), "VERSION=1.0", "CPath=/");
73+
InetAddress[] bound;
74+
if (conf.zeroconfListenAll()) {
75+
bound = getAllInterfacesAddresses();
76+
} else {
77+
String[] interfaces = conf.zeroconfInterfaces();
78+
if (interfaces.length == 0) {
79+
bound = new InetAddress[]{InetAddress.getLoopbackAddress()};
80+
} else {
81+
List<InetAddress> list = new ArrayList<>();
82+
for (String str : interfaces) addAddressForInterfaceName(list, str);
83+
bound = list.toArray(new InetAddress[0]);
84+
}
85+
}
86+
87+
LOGGER.debug("Registering service on " + Arrays.toString(bound));
88+
89+
ServiceInstance service = new ServiceInstance(new ServiceName("librespot._spotify-connect._tcp.local."), 0, 0, port, Name.fromString("local."), bound, "VERSION=1.0", "CPath=/");
7790
spotifyConnectService = mDnsService.register(service);
7891
if (spotifyConnectService == null)
7992
throw new IOException("Failed registering SpotifyConnect service!");
80-
8193
LOGGER.info("SpotifyConnect service registered successfully!");
8294
}
8395

96+
private static void addAddressForInterfaceName(List<InetAddress> list, @NotNull String name) throws SocketException {
97+
NetworkInterface nif = NetworkInterface.getByName(name);
98+
if (nif == null) {
99+
LOGGER.warn(String.format("Interface %s doesn't exists.", name));
100+
return;
101+
}
102+
103+
addAddressOfInterface(list, nif);
104+
}
105+
106+
private static void addAddressOfInterface(List<InetAddress> list, @NotNull NetworkInterface nif) {
107+
LOGGER.trace(String.format("Adding addresses of %s (displayName: %s)", nif.getName(), nif.getDisplayName()));
108+
Enumeration<InetAddress> ias = nif.getInetAddresses();
109+
while (ias.hasMoreElements())
110+
list.add(ias.nextElement());
111+
}
112+
113+
@NotNull
114+
private static InetAddress[] getAllInterfacesAddresses() throws SocketException {
115+
List<InetAddress> list = new ArrayList<>();
116+
Enumeration<NetworkInterface> is = NetworkInterface.getNetworkInterfaces();
117+
while (is.hasMoreElements()) addAddressOfInterface(list, is.nextElement());
118+
return list.toArray(new InetAddress[0]);
119+
}
120+
84121
@Override
85122
public void close() throws IOException {
86123
mDnsService.unregister(spotifyConnectService);
@@ -194,6 +231,13 @@ Authentication.LoginCredentials lockUntilCredentials() throws InterruptedExcepti
194231
}
195232
}
196233

234+
public interface Configuration {
235+
boolean zeroconfListenAll();
236+
237+
@NotNull
238+
String[] zeroconfInterfaces();
239+
}
240+
197241
private class HttpRunner implements Runnable, Closeable {
198242
private final ServerSocket serverSocket;
199243
private volatile boolean shouldStop = false;
@@ -297,4 +341,4 @@ public void close() throws IOException {
297341
serverSocket.close();
298342
}
299343
}
300-
}
344+
}

0 commit comments

Comments
 (0)