Reset SAS for device transfer on reconnect and hard abort if disconnected during transfer.

This commit is contained in:
Cody Henthorne
2026-06-09 13:13:35 -04:00
parent 6d260ab63d
commit 9478cdf049
3 changed files with 40 additions and 7 deletions
@@ -24,7 +24,9 @@ public final class DeviceTransferSetupViewModel extends ViewModel {
public DeviceTransferSetupViewModel() {
this.store = new Store<>(new DeviceSetupState());
this.distinctStepChanges = LiveDataUtil.distinctUntilChanged(this.store.getStateLiveData(), (current, next) -> current.getCurrentSetupStep() == next.getCurrentSetupStep());
this.distinctStepChanges = LiveDataUtil.distinctUntilChanged(this.store.getStateLiveData(),
(current, next) -> current.getCurrentSetupStep() == next.getCurrentSetupStep() &&
current.getAuthenticationCode() == next.getAuthenticationCode());
}
public @NonNull LiveData<DeviceSetupState> getState() {
@@ -69,6 +69,10 @@ final class NetworkClientThread extends Thread {
while (shouldKeepRunning()) {
Log.i(TAG, "Attempting to connect to server... tries: " + validClientAttemptsRemaining);
resetVerification();
boolean transferStarted = false;
try {
SelfSignedIdentity.ApprovingTrustManager trustManager = new SelfSignedIdentity.ApprovingTrustManager();
client = (SSLSocket) SelfSignedIdentity.getApprovingSocketFactory(trustManager).createSocket();
@@ -105,6 +109,7 @@ final class NetworkClientThread extends Thread {
throw new DeviceTransferAuthentication.DeviceTransferAuthenticationException(e);
}
transferStarted = true;
handler.sendEmptyMessage(NETWORK_CLIENT_CONNECTED);
clientTask.run(context, outputStream);
outputStream.flush();
@@ -119,9 +124,14 @@ final class NetworkClientThread extends Thread {
success = true;
isRunning = false;
} catch (IOException e) {
Log.w(TAG, "Error connecting to server", e);
validClientAttemptsRemaining--;
isRunning = validClientAttemptsRemaining > 0;
if (transferStarted) {
Log.w(TAG, "Lost connection after the transfer started, aborting instead of retrying.", e);
isRunning = false;
} else {
Log.w(TAG, "Error connecting to server", e);
validClientAttemptsRemaining--;
isRunning = validClientAttemptsRemaining > 0;
}
}
} catch (Exception e) {
Log.w(TAG, e);
@@ -143,6 +153,12 @@ final class NetworkClientThread extends Thread {
handler.sendEmptyMessage(NETWORK_CLIENT_STOPPED);
}
private void resetVerification() {
synchronized (verificationLock) {
isVerified = null;
}
}
private void awaitAuthenticationCodeVerification() throws DeviceTransferAuthentication.DeviceTransferAuthenticationException {
synchronized (verificationLock) {
try {
@@ -64,6 +64,9 @@ final class NetworkServerThread extends Thread {
handler.sendMessage(handler.obtainMessage(NETWORK_SERVER_STARTED, serverSocket.getLocalPort(), 0));
while (shouldKeepRunning() && !serverSocket.isClosed()) {
Log.i(TAG, "Waiting for client socket accept...");
boolean transferStarted = false;
try {
clientSocket = serverSocket.accept();
@@ -71,6 +74,8 @@ final class NetworkServerThread extends Thread {
break;
}
resetVerification();
InputStream inputStream = clientSocket.getInputStream();
OutputStream outputStream = clientSocket.getOutputStream();
int authenticationCode = DeviceTransferAuthentication.generateServerAuthenticationCode(keys.getX509Encoded(), inputStream, outputStream);
@@ -93,16 +98,20 @@ final class NetworkServerThread extends Thread {
throw new DeviceTransferAuthentication.DeviceTransferAuthenticationException(e);
}
transferStarted = true;
handler.sendEmptyMessage(NETWORK_CLIENT_CONNECTED);
serverTask.run(context, inputStream);
outputStream.write(0x53);
outputStream.flush();
} catch (IOException e) {
if (isRunning) {
Log.i(TAG, "Error connecting with client or server socket closed.", e);
} else {
if (!isRunning) {
Log.i(TAG, "Server shutting down...");
} else if (transferStarted) {
Log.w(TAG, "Lost connection after the transfer started, aborting instead of accepting another client.", e);
isRunning = false;
} else {
Log.i(TAG, "Error connecting with client or server socket closed.", e);
}
} finally {
StreamUtil.close(clientSocket);
@@ -122,6 +131,12 @@ final class NetworkServerThread extends Thread {
handler.sendEmptyMessage(NETWORK_SERVER_STOPPED);
}
private void resetVerification() {
synchronized (verificationLock) {
isVerified = null;
}
}
private void awaitAuthenticationCodeVerification() throws DeviceTransferAuthentication.DeviceTransferAuthenticationException {
synchronized (verificationLock) {
try {