Skip to content

Commit 704ca19

Browse files
committed
ApResolver: Use OkHttpClient for requesting the list
With the old implementation, the ap request wasn't going through the proxy (if there was one configured). Now, it uses the OkHttpClient we use in other parts of the app which will be configured to use the proxy if needed.
1 parent 18f53d5 commit 704ca19

4 files changed

Lines changed: 58 additions & 44 deletions

File tree

lib/src/main/java/xyz/gianlu/librespot/core/ApResolver.java

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,15 @@
2020
import com.google.gson.JsonElement;
2121
import com.google.gson.JsonObject;
2222
import com.google.gson.JsonParser;
23+
import okhttp3.OkHttpClient;
24+
import okhttp3.Request;
25+
import okhttp3.Response;
2326
import org.jetbrains.annotations.NotNull;
2427
import org.slf4j.Logger;
2528
import org.slf4j.LoggerFactory;
2629

2730
import java.io.IOException;
28-
import java.io.InputStreamReader;
2931
import java.io.Reader;
30-
import java.net.HttpURLConnection;
31-
import java.net.URL;
3232
import java.util.ArrayList;
3333
import java.util.HashMap;
3434
import java.util.List;
@@ -40,29 +40,36 @@
4040
*/
4141
public final class ApResolver {
4242
private static final String BASE_URL = "http://apresolve.spotify.com/";
43-
private static final Map<String, List<String>> pool = new HashMap<>(3);
4443
private static final Logger LOGGER = LoggerFactory.getLogger(ApResolver.class);
45-
private static volatile boolean poolReady = false;
4644

47-
public static void fillPool() throws IOException {
48-
if (!poolReady) request("accesspoint", "dealer", "spclient");
45+
private final OkHttpClient client;
46+
private final Map<String, List<String>> pool = new HashMap<>(3);
47+
private volatile boolean poolReady = false;
48+
49+
public ApResolver(OkHttpClient client) throws IOException {
50+
this.client = client;
51+
fillPool();
4952
}
5053

51-
public static void refreshPool() throws IOException {
54+
private void fillPool() throws IOException {
55+
request("accesspoint", "dealer", "spclient");
56+
}
57+
58+
public void refreshPool() throws IOException {
5259
poolReady = false;
5360
pool.clear();
54-
request("accesspoint", "dealer", "spclient");
61+
fillPool();
5562
}
5663

5764
@NotNull
58-
private static List<String> getUrls(@NotNull JsonObject body, @NotNull String type) {
65+
private List<String> getUrls(@NotNull JsonObject body, @NotNull String type) {
5966
JsonArray aps = body.getAsJsonArray(type);
6067
List<String> list = new ArrayList<>(aps.size());
6168
for (JsonElement ap : aps) list.add(ap.getAsString());
6269
return list;
6370
}
6471

65-
private static void request(@NotNull String... types) throws IOException {
72+
private void request(@NotNull String... types) throws IOException {
6673
if (types.length == 0) throw new IllegalArgumentException();
6774

6875
StringBuilder url = new StringBuilder(BASE_URL + "?");
@@ -71,28 +78,29 @@ private static void request(@NotNull String... types) throws IOException {
7178
url.append("type=").append(types[i]);
7279
}
7380

74-
HttpURLConnection conn = (HttpURLConnection) new URL(url.toString()).openConnection();
75-
conn.connect();
76-
77-
try (Reader reader = new InputStreamReader(conn.getInputStream())) {
78-
JsonObject obj = JsonParser.parseReader(reader).getAsJsonObject();
79-
HashMap<String, List<String>> map = new HashMap<>();
80-
for (String type : types)
81-
map.put(type, getUrls(obj, type));
81+
Request request = new Request.Builder()
82+
.url(url.toString())
83+
.build();
84+
Response response = client.newCall(request).execute();
85+
if (response.isSuccessful()) {
86+
try (Reader reader = response.body().charStream()) {
87+
JsonObject obj = JsonParser.parseReader(reader).getAsJsonObject();
88+
HashMap<String, List<String>> map = new HashMap<>();
89+
for (String type : types)
90+
map.put(type, getUrls(obj, type));
91+
92+
synchronized (pool) {
93+
pool.putAll(map);
94+
poolReady = true;
95+
pool.notifyAll();
96+
}
8297

83-
synchronized (pool) {
84-
pool.putAll(map);
85-
poolReady = true;
86-
pool.notifyAll();
98+
LOGGER.info("Loaded aps into pool: " + pool);
8799
}
88-
89-
LOGGER.info("Loaded aps into pool: " + pool);
90-
} finally {
91-
conn.disconnect();
92100
}
93101
}
94102

95-
private static void waitForPool() {
103+
private void waitForPool() {
96104
if (!poolReady) {
97105
synchronized (pool) {
98106
try {
@@ -105,7 +113,7 @@ private static void waitForPool() {
105113
}
106114

107115
@NotNull
108-
private static String getRandomOf(@NotNull String type) {
116+
private String getRandomOf(@NotNull String type) {
109117
waitForPool();
110118

111119
List<String> urls = pool.get(type);
@@ -114,17 +122,17 @@ private static String getRandomOf(@NotNull String type) {
114122
}
115123

116124
@NotNull
117-
public static String getRandomDealer() {
125+
public String getRandomDealer() {
118126
return getRandomOf("dealer");
119127
}
120128

121129
@NotNull
122-
public static String getRandomSpclient() {
130+
public String getRandomSpclient() {
123131
return getRandomOf("spclient");
124132
}
125133

126134
@NotNull
127-
public static String getRandomAccesspoint() {
135+
public String getRandomAccesspoint() {
128136
return getRandomOf("accesspoint");
129137
}
130138
}

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

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ public final class Session implements Closeable {
100100
(byte) 0xeb, (byte) 0x00, (byte) 0x06, (byte) 0xa2, (byte) 0x5a, (byte) 0xee, (byte) 0xa1, (byte) 0x1b, (byte) 0x13, (byte) 0x87, (byte) 0x3c, (byte) 0xd7,
101101
(byte) 0x19, (byte) 0xe6, (byte) 0x55, (byte) 0xbd
102102
};
103+
private final ApResolver apResolver;
103104
private final DiffieHellman keys;
104105
private final Inner inner;
105106
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new NameThreadFactory(r -> "session-scheduler-" + r.hashCode()));
@@ -128,11 +129,13 @@ public final class Session implements Closeable {
128129
private volatile boolean closing = false;
129130
private volatile ScheduledFuture<?> scheduledReconnect = null;
130131

131-
private Session(@NotNull Inner inner, @NotNull String addr) throws IOException {
132+
private Session(@NotNull Inner inner) throws IOException {
132133
this.inner = inner;
133134
this.keys = new DiffieHellman(inner.random);
134-
this.conn = ConnectionHolder.create(addr, inner.conf);
135135
this.client = createClient(inner.conf);
136+
this.apResolver = new ApResolver(client);
137+
String addr = apResolver.getRandomAccesspoint();
138+
this.conn = ConnectionHolder.create(addr, inner.conf);
136139

137140
LOGGER.info("Created new session! {deviceId: {}, ap: {}, proxy: {}} ", inner.deviceId, addr, inner.conf.proxyEnabled);
138141
}
@@ -566,6 +569,11 @@ public void send(Packet.Type cmd, byte[] payload) throws IOException {
566569
}
567570
}
568571

572+
@NotNull
573+
public ApResolver apResolver() {
574+
return apResolver;
575+
}
576+
569577
@NotNull
570578
public MercuryClient mercury() {
571579
waitAuthLock();
@@ -710,14 +718,14 @@ private void reconnect() {
710718
}
711719

712720
try {
713-
ApResolver.refreshPool();
721+
apResolver.refreshPool();
714722

715723
if (conn != null) {
716724
conn.socket.close();
717725
receiver.stop();
718726
}
719727

720-
conn = ConnectionHolder.create(ApResolver.getRandomAccesspoint(), inner.conf);
728+
conn = ConnectionHolder.create(apResolver.getRandomAccesspoint(), inner.conf);
721729
connect();
722730
authenticatePartial(Authentication.LoginCredentials.newBuilder()
723731
.setUsername(apWelcome.getCanonicalUsername())
@@ -1021,10 +1029,9 @@ public Session create() throws IOException, GeneralSecurityException, SpotifyAut
10211029
if (loginCredentials == null)
10221030
throw new IllegalStateException("You must select an authentication method.");
10231031

1024-
ApResolver.fillPool();
10251032
TimeProvider.init(conf);
10261033

1027-
Session session = new Session(new Inner(deviceType, deviceName, deviceId, preferredLocale, conf), ApResolver.getRandomAccesspoint());
1034+
Session session = new Session(new Inner(deviceType, deviceName, deviceId, preferredLocale, conf));
10281035
session.connect();
10291036
session.authenticate(loginCredentials);
10301037
return session;
@@ -1253,9 +1260,9 @@ private ConnectionHolder(@NotNull Socket socket) throws IOException {
12531260

12541261
@NotNull
12551262
static ConnectionHolder create(@NotNull String addr, @NotNull Configuration conf) throws IOException {
1256-
int colon = addr.indexOf(':');
1257-
String apAddr = addr.substring(0, colon);
1258-
int apPort = Integer.parseInt(addr.substring(colon + 1));
1263+
String[] split = addr.split(":");
1264+
String apAddr = split[0];
1265+
int apPort = Integer.parseInt(split[1]);
12591266
if (!conf.proxyEnabled || conf.proxyType == Proxy.Type.DIRECT)
12601267
return new ConnectionHolder(new Socket(apAddr, apPort));
12611268

lib/src/main/java/xyz/gianlu/librespot/dealer/ApiClient.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public final class ApiClient {
4646

4747
public ApiClient(@NotNull Session session) {
4848
this.session = session;
49-
this.baseUrl = "https://" + ApResolver.getRandomSpclient();
49+
this.baseUrl = "https://" + session.apResolver().getRandomSpclient();
5050
}
5151

5252
@NotNull

lib/src/main/java/xyz/gianlu/librespot/dealer/DealerClient.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import xyz.gianlu.librespot.common.BytesArrayList;
3232
import xyz.gianlu.librespot.common.NameThreadFactory;
3333
import xyz.gianlu.librespot.common.Utils;
34-
import xyz.gianlu.librespot.core.ApResolver;
3534
import xyz.gianlu.librespot.core.Session;
3635
import xyz.gianlu.librespot.mercury.MercuryClient;
3736

@@ -76,7 +75,7 @@ private static Map<String, String> getHeaders(@NotNull JsonObject obj) {
7675
*/
7776
public synchronized void connect() throws IOException, MercuryClient.MercuryException {
7877
conn = new ConnectionHolder(session, new Request.Builder()
79-
.url(String.format("wss://%s/?access_token=%s", ApResolver.getRandomDealer(), session.tokens().get("playlist-read")))
78+
.url(String.format("wss://%s/?access_token=%s", session.apResolver().getRandomDealer(), session.tokens().get("playlist-read")))
8079
.build());
8180
}
8281

0 commit comments

Comments
 (0)