import java.io.IOException;
import java.net.URI;
import java.util.concurrent.TimeoutException;
+import java.util.function.Consumer;
public class ProvisioningManager {
private final PathConfig pathConfig;
private final ServiceEnvironmentConfig serviceEnvironmentConfig;
private final String userAgent;
+ private final Consumer<Manager> newManagerListener;
private final SignalServiceAccountManager accountManager;
private final IdentityKeyPair tempIdentityKey;
private final int registrationId;
private final String password;
- ProvisioningManager(PathConfig pathConfig, ServiceEnvironmentConfig serviceEnvironmentConfig, String userAgent) {
+ ProvisioningManager(
+ PathConfig pathConfig,
+ ServiceEnvironmentConfig serviceEnvironmentConfig,
+ String userAgent,
+ final Consumer<Manager> newManagerListener
+ ) {
this.pathConfig = pathConfig;
this.serviceEnvironmentConfig = serviceEnvironmentConfig;
this.userAgent = userAgent;
+ this.newManagerListener = newManagerListener;
tempIdentityKey = KeyUtils.generateIdentityKeyPair();
registrationId = KeyHelper.generateRegistrationId(false);
public static ProvisioningManager init(
File settingsPath, ServiceEnvironment serviceEnvironment, String userAgent
+ ) {
+ return init(settingsPath, serviceEnvironment, userAgent, null);
+ }
+
+ public static ProvisioningManager init(
+ File settingsPath,
+ ServiceEnvironment serviceEnvironment,
+ String userAgent,
+ Consumer<Manager> newManagerListener
) {
var pathConfig = PathConfig.createDefault(settingsPath);
final var serviceConfiguration = ServiceConfig.getServiceEnvironmentConfig(serviceEnvironment, userAgent);
- return new ProvisioningManager(pathConfig, serviceConfiguration, userAgent);
+ return new ProvisioningManager(pathConfig, serviceConfiguration, userAgent, newManagerListener);
}
public URI getDeviceLinkUri() throws TimeoutException, IOException {
return new DeviceLinkInfo(deviceUuid, tempIdentityKey.getPublicKey().getPublicKey()).createDeviceLinkUri();
}
- public Manager finishDeviceLink(String deviceName) throws IOException, TimeoutException, UserAlreadyExists {
+ public String finishDeviceLink(String deviceName) throws IOException, TimeoutException, UserAlreadyExists {
var ret = accountManager.getNewDeviceRegistration(tempIdentityKey);
var number = ret.getNumber();
logger.info("Received link information from {}, linking in progress ...", number);
- if (SignalAccount.userExists(pathConfig.getDataPath(), number) && !canRelinkExistingAccount(number)) {
- throw new UserAlreadyExists(number, SignalAccount.getFileName(pathConfig.getDataPath(), number));
+ if (SignalAccount.userExists(pathConfig.dataPath(), number) && !canRelinkExistingAccount(number)) {
+ throw new UserAlreadyExists(number, SignalAccount.getFileName(pathConfig.dataPath(), number));
}
var encryptedDeviceName = deviceName == null
? null
: DeviceNameUtil.encryptDeviceName(deviceName, ret.getIdentity().getPrivateKey());
+ logger.debug("Finishing new device registration");
var deviceId = accountManager.finishNewDeviceRegistration(ret.getProvisioningCode(),
false,
true,
SignalAccount account = null;
try {
- account = SignalAccount.createOrUpdateLinkedAccount(pathConfig.getDataPath(),
+ account = SignalAccount.createOrUpdateLinkedAccount(pathConfig.dataPath(),
number,
- ret.getUuid(),
+ ret.getAci(),
password,
encryptedDeviceName,
deviceId,
profileKey,
TrustNewIdentity.ON_FIRST_USE);
- Manager m = null;
+ ManagerImpl m = null;
try {
- m = new Manager(account, pathConfig, serviceEnvironmentConfig, userAgent);
+ m = new ManagerImpl(account, pathConfig, serviceEnvironmentConfig, userAgent);
+ account = null;
+ logger.debug("Refreshing pre keys");
try {
m.refreshPreKeys();
} catch (Exception e) {
- logger.error("Failed to check new account state.");
- throw e;
+ logger.error("Failed to refresh pre keys.");
}
+ logger.debug("Requesting sync data");
try {
m.requestAllSyncData();
} catch (Exception e) {
- logger.error("Failed to request sync messages from linked device.");
- throw e;
+ logger.error(
+ "Failed to request sync messages from linked device, data can be requested again with `sendSyncRequest`.");
}
- final var result = m;
- account = null;
- m = null;
-
- return result;
+ if (newManagerListener != null) {
+ newManagerListener.accept(m);
+ m = null;
+ }
+ return number;
} finally {
if (m != null) {
m.close();
private boolean canRelinkExistingAccount(final String number) throws IOException {
final SignalAccount signalAccount;
try {
- signalAccount = SignalAccount.load(pathConfig.getDataPath(), number, false, TrustNewIdentity.ON_FIRST_USE);
+ signalAccount = SignalAccount.load(pathConfig.dataPath(), number, false, TrustNewIdentity.ON_FIRST_USE);
} catch (IOException e) {
logger.debug("Account in use or failed to load.", e);
return false;
return false;
}
- final var m = new Manager(signalAccount, pathConfig, serviceEnvironmentConfig, userAgent);
+ final var m = new ManagerImpl(signalAccount, pathConfig, serviceEnvironmentConfig, userAgent);
try (m) {
m.checkAccountState();
} catch (AuthorizationFailedException ignored) {