diff --git a/lib/src/main/java/org/asamk/signal/manager/internal/ProvisioningManagerImpl.java b/lib/src/main/java/org/asamk/signal/manager/internal/ProvisioningManagerImpl.java index b438a39b..779a4a0b 100644 --- a/lib/src/main/java/org/asamk/signal/manager/internal/ProvisioningManagerImpl.java +++ b/lib/src/main/java/org/asamk/signal/manager/internal/ProvisioningManagerImpl.java @@ -191,14 +191,18 @@ public class ProvisioningManagerImpl implements ProvisioningManager, Closeable { : new MediaRootBackupKey(msg.mediaRootBackupKey.toByteArray()); SignalAccount account = null; + var cleanUpPartialAccountOnFailure = false; + var linkingFinished = false; try { if (!accountExists) { account = SignalAccount.createLinkedAccount(pathConfig.dataPath(), accountPath, serviceEnvironmentConfig.type(), Settings.DEFAULT); + cleanUpPartialAccountOnFailure = true; } else { account = SignalAccount.load(pathConfig.dataPath(), accountPath, true, Settings.DEFAULT); + cleanUpPartialAccountOnFailure = false; } account.setProvisioningData(number, @@ -241,6 +245,7 @@ public class ProvisioningManagerImpl implements ProvisioningManager, Closeable { final var deviceId = Integer.parseInt(registerResponse.getDeviceId()); account.finishLinking(deviceId, aciPreKeys, pniPreKeys); + linkingFinished = true; ManagerImpl m = null; try { @@ -277,6 +282,12 @@ public class ProvisioningManagerImpl implements ProvisioningManager, Closeable { m.close(); } } + } catch (Exception e) { + if (!linkingFinished && cleanUpPartialAccountOnFailure && account != null) { + cleanupPartialAccount(account, accountPath, e); + account = null; + } + throw e; } finally { if (account != null) { account.close(); @@ -289,6 +300,28 @@ public class ProvisioningManagerImpl implements ProvisioningManager, Closeable { socketHandle.close(); } + private void cleanupPartialAccount(final SignalAccount account, final String accountPath, final Exception cause) { + logger.warn("Link attempt failed before registration completed, removing partial account state for {}.", + accountPath, + cause); + try { + account.deleteAccountData(); + } catch (IOException cleanupError) { + logger.warn("Failed to delete partial account data for {}: {}", + accountPath, + cleanupError.getMessage(), + cleanupError); + } + try { + accountsStore.removeAccount(accountPath); + } catch (RuntimeException cleanupError) { + logger.warn("Failed to remove partial account entry for {}: {}", + accountPath, + cleanupError.getMessage(), + cleanupError); + } + } + private boolean canRelinkExistingAccount(final String accountPath) throws IOException { final SignalAccount signalAccount; try { @@ -302,6 +335,11 @@ public class ProvisioningManagerImpl implements ProvisioningManager, Closeable { } try (signalAccount) { + if (signalAccount.getDeviceId() <= 0) { + logger.debug("Account has invalid deviceId {}, allowing relink.", + signalAccount.getDeviceId()); + return true; + } if (signalAccount.isPrimaryDevice()) { logger.debug("Account is a primary device."); return false; diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java b/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java index 7e2c2e5c..6a6713c9 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java @@ -1731,7 +1731,7 @@ public class SignalAccount implements Closeable { } public boolean isRegistered() { - return registered; + return registered && deviceId > 0; } public void setRegistered(final boolean registered) {