Skip to content

Commit edc7354

Browse files
committed
Fixed race condition when reconnecting
1 parent 39018b7 commit edc7354

File tree

1 file changed

+38
-3
lines changed

1 file changed

+38
-3
lines changed

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

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import java.util.concurrent.ExecutorService;
3737
import java.util.concurrent.Executors;
3838
import java.util.concurrent.TimeUnit;
39+
import java.util.concurrent.atomic.AtomicBoolean;
3940

4041
/**
4142
* @author Gianlu
@@ -45,6 +46,7 @@ public class Session implements Closeable {
4546
private final DiffieHellman keys;
4647
private final Inner inner;
4748
private final ExecutorService executorService = Executors.newCachedThreadPool(new NameThreadFactory(r -> "handle-packet-" + r.hashCode()));
49+
private final AtomicBoolean authLock = new AtomicBoolean(false);
4850
private ConnectionHolder conn;
4951
private CipherPair cipherPair;
5052
private Receiver receiver;
@@ -188,12 +190,21 @@ void connect() throws IOException, GeneralSecurityException, SpotifyAuthenticati
188190
cipherPair = new CipherPair(Arrays.copyOfRange(data.toByteArray(), 0x14, 0x34),
189191
Arrays.copyOfRange(data.toByteArray(), 0x34, 0x54));
190192

193+
synchronized (authLock) {
194+
authLock.set(true);
195+
}
196+
191197
LOGGER.info("Connected successfully!");
192198
}
193199

194200
void authenticate(@NotNull Authentication.LoginCredentials credentials) throws IOException, GeneralSecurityException, SpotifyAuthenticationException, MercuryClient.PubSubException, SpotifyIrc.IrcException {
195201
authenticatePartial(credentials);
196202

203+
synchronized (authLock) {
204+
authLock.set(false);
205+
authLock.notifyAll();
206+
}
207+
197208
mercuryClient = new MercuryClient(this);
198209

199210
audioKeyManager = new AudioKeyManager(this);
@@ -219,7 +230,7 @@ private void authenticatePartial(@NotNull Authentication.LoginCredentials creden
219230
.setVersionString(Version.versionString())
220231
.build();
221232

222-
send(Packet.Type.Login, clientResponseEncrypted.toByteArray());
233+
sendUnchecked(Packet.Type.Login, clientResponseEncrypted.toByteArray());
223234

224235
Packet packet = cipherPair.receiveEncoded(conn.in);
225236
if (packet.is(Packet.Type.APWelcome)) {
@@ -230,7 +241,7 @@ private void authenticatePartial(@NotNull Authentication.LoginCredentials creden
230241

231242
byte[] bytes0x0f = new byte[20];
232243
random().nextBytes(bytes0x0f);
233-
send(Packet.Type.Unknown_0x0f, bytes0x0f);
244+
sendUnchecked(Packet.Type.Unknown_0x0f, bytes0x0f);
234245
} else if (packet.is(Packet.Type.AuthFailure)) {
235246
throw new SpotifyAuthenticationException(Keyexchange.APLoginFailed.parseFrom(packet.payload));
236247
} else {
@@ -267,47 +278,71 @@ public void close() throws IOException {
267278
LOGGER.info(String.format("Closed session. {deviceId: %s, ap: %s} ", inner.deviceId, conn.socket.getInetAddress()));
268279
}
269280

270-
public void send(Packet.Type cmd, byte[] payload) throws IOException {
281+
private void sendUnchecked(Packet.Type cmd, byte[] payload) throws IOException {
271282
cipherPair.sendEncoded(conn.out, cmd.val, payload);
272283
}
273284

285+
private void waitAuthLock() {
286+
synchronized (authLock) {
287+
if (authLock.get()) {
288+
try {
289+
authLock.wait();
290+
} catch (InterruptedException ex) {
291+
throw new RuntimeException(ex);
292+
}
293+
}
294+
}
295+
}
296+
297+
public void send(Packet.Type cmd, byte[] payload) throws IOException {
298+
waitAuthLock();
299+
sendUnchecked(cmd, payload);
300+
}
301+
274302
@NotNull
275303
public MercuryClient mercury() {
304+
waitAuthLock();
276305
if (mercuryClient == null) throw new IllegalStateException("Session isn't authenticated!");
277306
return mercuryClient;
278307
}
279308

280309
@NotNull
281310
public AudioKeyManager audioKey() {
311+
waitAuthLock();
282312
if (audioKeyManager == null) throw new IllegalStateException("Session isn't authenticated!");
283313
return audioKeyManager;
284314
}
285315

286316
@NotNull
287317
public ChannelManager channel() {
318+
waitAuthLock();
288319
if (channelManager == null) throw new IllegalStateException("Session isn't authenticated!");
289320
return channelManager;
290321
}
291322

292323
@NotNull
293324
public SpotifyIrc spirc() {
325+
waitAuthLock();
294326
if (spirc == null) throw new IllegalStateException("Session isn't authenticated!");
295327
return spirc;
296328
}
297329

298330
@NotNull
299331
public Player player() {
332+
waitAuthLock();
300333
if (player == null) throw new IllegalStateException("Session isn't authenticated!");
301334
return player;
302335
}
303336

304337
@NotNull
305338
public Authentication.APWelcome apWelcome() {
339+
waitAuthLock();
306340
if (apWelcome == null) throw new IllegalStateException("Session isn't authenticated!");
307341
return apWelcome;
308342
}
309343

310344
public boolean valid() {
345+
waitAuthLock();
311346
return apWelcome != null && conn != null && !conn.socket.isClosed();
312347
}
313348

0 commit comments

Comments
 (0)