3636import java .util .concurrent .ExecutorService ;
3737import java .util .concurrent .Executors ;
3838import 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