X-Git-Url: https://git.nmode.ca/signal-cli/blobdiff_plain/d72b838560b1a4186ac121c7d605773b49fcdf46..5cccf521032954d7ad8e3f70e3cbef2ce1293e85:/src/main/java/org/asamk/signal/dbus/DbusSignalControlImpl.java diff --git a/src/main/java/org/asamk/signal/dbus/DbusSignalControlImpl.java b/src/main/java/org/asamk/signal/dbus/DbusSignalControlImpl.java index be628bde..f80b91d6 100644 --- a/src/main/java/org/asamk/signal/dbus/DbusSignalControlImpl.java +++ b/src/main/java/org/asamk/signal/dbus/DbusSignalControlImpl.java @@ -3,82 +3,34 @@ package org.asamk.signal.dbus; import org.asamk.SignalControl; import org.asamk.signal.BaseConfig; import org.asamk.signal.DbusConfig; -import org.asamk.signal.commands.SignalCreator; import org.asamk.signal.manager.Manager; +import org.asamk.signal.manager.MultiAccountManager; import org.asamk.signal.manager.ProvisioningManager; import org.asamk.signal.manager.RegistrationManager; -import org.asamk.signal.manager.UserAlreadyExists; +import org.asamk.signal.manager.api.UserAlreadyExistsException; +import org.asamk.signal.manager.api.CaptchaRequiredException; +import org.asamk.signal.manager.api.IncorrectPinException; +import org.asamk.signal.manager.api.PinLockedException; import org.freedesktop.dbus.DBusPath; -import org.whispersystems.libsignal.util.Pair; -import org.whispersystems.signalservice.api.KeyBackupServicePinException; -import org.whispersystems.signalservice.api.KeyBackupSystemNoDataException; -import org.whispersystems.signalservice.api.push.exceptions.CaptchaRequiredException; -import org.whispersystems.signalservice.api.util.PhoneNumberFormatter; import java.io.IOException; import java.net.URI; -import java.util.ArrayList; +import java.net.URISyntaxException; +import java.nio.channels.OverlappingFileLockException; import java.util.List; import java.util.concurrent.TimeoutException; -import java.util.function.Function; -import java.util.stream.Collectors; public class DbusSignalControlImpl implements org.asamk.SignalControl { - private final SignalCreator c; - private final Function newManagerRunner; + private final MultiAccountManager c; - private final List> receiveThreads = new ArrayList<>(); - private final Object stopTrigger = new Object(); private final String objectPath; - public DbusSignalControlImpl( - final SignalCreator c, final Function newManagerRunner, final String objectPath - ) { + public DbusSignalControlImpl(final MultiAccountManager c, final String objectPath) { this.c = c; - this.newManagerRunner = newManagerRunner; this.objectPath = objectPath; } - public void addManager(Manager m) { - var thread = newManagerRunner.apply(m); - if (thread == null) { - return; - } - synchronized (receiveThreads) { - receiveThreads.add(new Pair<>(m, thread)); - } - } - - public void run() { - synchronized (stopTrigger) { - try { - stopTrigger.wait(); - } catch (InterruptedException ignored) { - } - } - - synchronized (receiveThreads) { - for (var t : receiveThreads) { - t.second().interrupt(); - } - } - while (true) { - final Thread thread; - synchronized (receiveThreads) { - if (receiveThreads.size() == 0) { - break; - } - var pair = receiveThreads.remove(0); - thread = pair.second(); - } - try { - thread.join(); - } catch (InterruptedException ignored) { - } - } - } - @Override public boolean isRemote() { return false; @@ -100,15 +52,17 @@ public class DbusSignalControlImpl implements org.asamk.SignalControl { public void registerWithCaptcha( final String number, final boolean voiceVerification, final String captcha ) throws Error.Failure, Error.InvalidNumber { - if (!PhoneNumberFormatter.isValidNumber(number, null)) { + if (!Manager.isValidNumber(number, null)) { throw new SignalControl.Error.InvalidNumber( - "Invalid username (phone number), make sure you include the country code."); + "Invalid account (phone number), make sure you include the country code."); } try (final RegistrationManager registrationManager = c.getNewRegistrationManager(number)) { registrationManager.register(voiceVerification, captcha); } catch (CaptchaRequiredException e) { String message = captcha == null ? "Captcha required for verification." : "Invalid captcha given."; throw new SignalControl.Error.RequiresCaptcha(message); + } catch (OverlappingFileLockException e) { + throw new SignalControl.Error.Failure("Account is already in use"); } catch (IOException e) { throw new SignalControl.Error.Failure(e.getClass().getSimpleName() + " " + e.getMessage()); } @@ -124,32 +78,60 @@ public class DbusSignalControlImpl implements org.asamk.SignalControl { final String number, final String verificationCode, final String pin ) throws Error.Failure, Error.InvalidNumber { try (final RegistrationManager registrationManager = c.getNewRegistrationManager(number)) { - final Manager manager = registrationManager.verifyAccount(verificationCode, pin); - addManager(manager); - } catch (IOException | KeyBackupSystemNoDataException | KeyBackupServicePinException e) { + registrationManager.verifyAccount(verificationCode, pin); + } catch (OverlappingFileLockException e) { + throw new SignalControl.Error.Failure("Account is already in use"); + } catch (IOException e) { throw new SignalControl.Error.Failure(e.getClass().getSimpleName() + " " + e.getMessage()); + } catch (PinLockedException e) { + throw new Error.Failure( + "Verification failed! This number is locked with a pin. Hours remaining until reset: " + + (e.getTimeRemaining() / 1000 / 60 / 60)); + } catch (IncorrectPinException e) { + throw new Error.Failure("Verification failed! Invalid pin, tries remaining: " + e.getTriesRemaining()); } } @Override public String link(final String newDeviceName) throws Error.Failure { try { - final ProvisioningManager provisioningManager = c.getNewProvisioningManager(); - final URI deviceLinkUri = provisioningManager.getDeviceLinkUri(); - new Thread(() -> { + final URI deviceLinkUri = c.getNewProvisioningDeviceLinkUri(); + final var thread = new Thread(() -> { + final ProvisioningManager provisioningManager = c.getProvisioningManagerFor(deviceLinkUri); try { - final Manager manager = provisioningManager.finishDeviceLink(newDeviceName); - addManager(manager); - } catch (IOException | TimeoutException | UserAlreadyExists e) { + provisioningManager.finishDeviceLink(newDeviceName); + } catch (IOException | TimeoutException | UserAlreadyExistsException e) { e.printStackTrace(); } - }).start(); + }); + thread.setName("dbus-link"); + thread.start(); + return deviceLinkUri.toString(); + } catch (TimeoutException | IOException e) { + throw new SignalControl.Error.Failure(e.getClass().getSimpleName() + " " + e.getMessage()); + } + } + + @Override + public String startLink() throws Error.Failure { + try { + final URI deviceLinkUri = c.getNewProvisioningDeviceLinkUri(); return deviceLinkUri.toString(); } catch (TimeoutException | IOException e) { throw new SignalControl.Error.Failure(e.getClass().getSimpleName() + " " + e.getMessage()); } } + @Override + public String finishLink(String deviceLinkUri, final String newDeviceName) throws Error.Failure { + try { + final var provisioningManager = c.getProvisioningManagerFor(new URI(deviceLinkUri)); + return provisioningManager.finishDeviceLink(newDeviceName); + } catch (TimeoutException | IOException | UserAlreadyExistsException | URISyntaxException e) { + throw new SignalControl.Error.Failure(e.getClass().getSimpleName() + " " + e.getMessage()); + } + } + @Override public String version() { return BaseConfig.PROJECT_VERSION; @@ -157,12 +139,11 @@ public class DbusSignalControlImpl implements org.asamk.SignalControl { @Override public List listAccounts() { - synchronized (receiveThreads) { - return receiveThreads.stream() - .map(Pair::first) - .map(Manager::getSelfNumber) - .map(u -> new DBusPath(DbusConfig.getObjectPath(u))) - .collect(Collectors.toList()); - } + return c.getAccountNumbers().stream().map(u -> new DBusPath(DbusConfig.getObjectPath(u))).toList(); + } + + @Override + public DBusPath getAccount(final String number) { + return new DBusPath(DbusConfig.getObjectPath(number)); } }