@@ -354,7 +354,7 @@ public Channel(
354354 * Establishes a connection to the associated remote cast device.
355355 *
356356 * @return {@code true} if a connection was established, {@code false} if
357- * there was no need .
357+ * a connection was already established .
358358 *
359359 * @throws KeyManagementException If there's a problem with key management
360360 * that prevents connection.
@@ -367,67 +367,95 @@ public Channel(
367367 * @apiNote This operation is blocking.
368368 */
369369 public boolean connect () throws IOException , NoSuchAlgorithmException , KeyManagementException {
370- synchronized (socketLock ) {
371- if (socket != null && socket .isConnected () && !socket .isClosed ()) {
372- // Already connected, nothing to do
373- return false ;
374- }
370+ Set <Session > closedSessions = null ;
371+ synchronized (sessionsLock ) {
372+ synchronized (socketLock ) {
373+ if (socket != null && socket .isConnected () && !socket .isClosed ()) {
374+ // Already connected, nothing to do
375+ return false ;
376+ }
375377
376- if (socket != null ) {
377- socket .close ();
378- socket = null ;
379- }
380- SSLContext sc = SSLContext .getInstance ("SSL" );
381- sc .init (null , new TrustManager [] {new X509TrustAllManager ()}, new SecureRandom ());
382- socket = sc .getSocketFactory ().createSocket ();
383- socket .setSoTimeout (0 );
384- socket .connect (address );
385-
386- // Authenticate
387- CastChannel .DeviceAuthMessage authMessage = CastChannel .DeviceAuthMessage .newBuilder ()
388- .setChallenge (CastChannel .AuthChallenge .newBuilder ().build ())
389- .build ();
378+ if (socket != null ) {
379+ if (!sessions .isEmpty ()) {
380+ closedSessions = new HashSet <>(sessions );
381+ sessions .clear ();
382+ }
390383
391- CastMessage msg = CastMessage .newBuilder ()
392- .setDestinationId (PLATFORM_RECEIVER_ID )
393- .setNamespace ("urn:x-cast:com.google.cast.tp.deviceauth" )
394- .setPayloadType (CastMessage .PayloadType .BINARY )
395- .setProtocolVersion (CastMessage .ProtocolVersion .CASTV2_1_0 )
396- .setSourceId (PLATFORM_SENDER_ID )
397- .setPayloadBinary (authMessage .toByteString ())
398- .build ();
384+ if (pingTimer != null ) {
385+ pingTimer .cancel ();
386+ pingTimer = null ;
387+ }
399388
400- write (msg );
401- ImmutableBinaryCastMessage response = (ImmutableBinaryCastMessage ) readMessage (socket .getInputStream ());
402- CastChannel .DeviceAuthMessage authResponse = CastChannel .DeviceAuthMessage .parseFrom (response .getPayload ());
403- if (authResponse .hasError ()) {
404- throw new CastException ("Authentication failed: " + authResponse .getError ().getErrorType ().toString ());
405- }
389+ if (inputHandler != null ) {
390+ inputHandler .stopProcessing ();
391+ inputHandler = null ;
392+ }
406393
407- // Make extra sure we're not losing the reference to a live thread
408- if (inputHandler != null ) {
409- inputHandler .stopProcessing ();
410- }
411- // Start input handler
412- inputHandler = new InputHandler (socket .getInputStream ());
413- inputHandler .start ();
394+ socket .close ();
395+ }
396+ SSLContext sc = SSLContext .getInstance ("SSL" );
397+ sc .init (null , new TrustManager [] {new X509TrustAllManager ()}, new SecureRandom ());
398+ socket = sc .getSocketFactory ().createSocket ();
399+ socket .setSoTimeout (0 );
400+ socket .connect (address );
401+
402+ // Authenticate
403+ CastChannel .DeviceAuthMessage authMessage = CastChannel .DeviceAuthMessage .newBuilder ()
404+ .setChallenge (CastChannel .AuthChallenge .newBuilder ().build ())
405+ .build ();
406+
407+ CastMessage msg = CastMessage .newBuilder ()
408+ .setDestinationId (PLATFORM_RECEIVER_ID )
409+ .setNamespace ("urn:x-cast:com.google.cast.tp.deviceauth" )
410+ .setPayloadType (CastMessage .PayloadType .BINARY )
411+ .setProtocolVersion (CastMessage .ProtocolVersion .CASTV2_1_0 )
412+ .setSourceId (PLATFORM_SENDER_ID )
413+ .setPayloadBinary (authMessage .toByteString ())
414+ .build ();
415+
416+ write (msg );
417+ ImmutableBinaryCastMessage response = (ImmutableBinaryCastMessage ) readMessage (socket .getInputStream ());
418+ CastChannel .DeviceAuthMessage authResponse = CastChannel .DeviceAuthMessage .parseFrom (response .getPayload ());
419+ if (authResponse .hasError ()) {
420+ throw new CastException ("Authentication failed: " + authResponse .getError ().getErrorType ().toString ());
421+ }
414422
415- // Send 'CONNECT' message to start session
416- write (
417- "urn:x-cast:com.google.cast.tp.connection" ,
418- new Connect (null , VirtualConnectionType .STRONG ),
419- PLATFORM_SENDER_ID ,
420- PLATFORM_RECEIVER_ID
421- );
423+ // Make extra sure we're not losing the reference to a live thread
424+ if (inputHandler != null ) {
425+ inputHandler .stopProcessing ();
426+ }
427+ // Start input handler
428+ inputHandler = new InputHandler (socket .getInputStream ());
429+ inputHandler .start ();
430+
431+ // Send 'CONNECT' message to start session
432+ write (
433+ "urn:x-cast:com.google.cast.tp.connection" ,
434+ new Connect (null , VirtualConnectionType .STRONG ),
435+ PLATFORM_SENDER_ID ,
436+ PLATFORM_RECEIVER_ID
437+ );
438+
439+ // Make extra sure that we're not losing the reference to a live timer
440+ if (pingTimer != null ) {
441+ pingTimer .cancel ();
442+ }
443+ // Start regular pinging
444+ PingTask pingTask = new PingTask ();
445+ pingTimer = new Timer (remoteName + " PING timer" );
446+ pingTimer .schedule (pingTask , 1000 , PING_PERIOD );
447+ }
448+ }
422449
423- // Make extra sure that we're not losing the reference to a live timer
424- if (pingTimer != null ) {
425- pingTimer .cancel ();
450+ cancelPendingDisconnected ();
451+ if (closedSessions != null ) {
452+ SessionClosedListener closedListener ;
453+ for (Session session : closedSessions ) {
454+ closedListener = session .getSessionClosedListener ();
455+ if (closedListener != null ) {
456+ closedListener .closed (session );
457+ }
426458 }
427- // Start regular pinging
428- PingTask pingTask = new PingTask ();
429- pingTimer = new Timer (remoteName + " PING timer" );
430- pingTimer .schedule (pingTask , 1000 , PING_PERIOD );
431459 }
432460
433461 // Reset the cached volume on every connect
0 commit comments