Skip to content

Commit f954afe

Browse files
committed
Perform full disconnect procedure during reconnect
1 parent 71e47f0 commit f954afe

1 file changed

Lines changed: 83 additions & 55 deletions

File tree

src/main/java/org/digitalmediaserver/cast/Channel.java

Lines changed: 83 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)