1 package org
.asamk
.signal
.dbus
;
3 import org
.asamk
.SignalControl
;
4 import org
.asamk
.signal
.BaseConfig
;
5 import org
.asamk
.signal
.DbusConfig
;
6 import org
.asamk
.signal
.commands
.SignalCreator
;
7 import org
.asamk
.signal
.manager
.Manager
;
8 import org
.asamk
.signal
.manager
.ProvisioningManager
;
9 import org
.asamk
.signal
.manager
.RegistrationManager
;
10 import org
.asamk
.signal
.manager
.UserAlreadyExists
;
11 import org
.asamk
.signal
.manager
.api
.CaptchaRequiredException
;
12 import org
.asamk
.signal
.manager
.api
.IncorrectPinException
;
13 import org
.asamk
.signal
.manager
.api
.Pair
;
14 import org
.asamk
.signal
.manager
.api
.PinLockedException
;
15 import org
.freedesktop
.dbus
.DBusPath
;
17 import java
.io
.IOException
;
19 import java
.util
.ArrayList
;
20 import java
.util
.List
;
21 import java
.util
.concurrent
.TimeoutException
;
22 import java
.util
.function
.Function
;
23 import java
.util
.stream
.Collectors
;
25 public class DbusSignalControlImpl
implements org
.asamk
.SignalControl
{
27 private final SignalCreator c
;
28 private final Function
<Manager
, Thread
> newManagerRunner
;
30 private final List
<Pair
<Manager
, Thread
>> receiveThreads
= new ArrayList
<>();
31 private final Object stopTrigger
= new Object();
32 private final String objectPath
;
34 public DbusSignalControlImpl(
35 final SignalCreator c
, final Function
<Manager
, Thread
> newManagerRunner
, final String objectPath
38 this.newManagerRunner
= newManagerRunner
;
39 this.objectPath
= objectPath
;
42 public void addManager(Manager m
) {
43 var thread
= newManagerRunner
.apply(m
);
47 synchronized (receiveThreads
) {
48 receiveThreads
.add(new Pair
<>(m
, thread
));
53 synchronized (stopTrigger
) {
56 } catch (InterruptedException ignored
) {
60 synchronized (receiveThreads
) {
61 for (var t
: receiveThreads
) {
62 t
.second().interrupt();
67 synchronized (receiveThreads
) {
68 if (receiveThreads
.size() == 0) {
71 var pair
= receiveThreads
.remove(0);
72 thread
= pair
.second();
76 } catch (InterruptedException ignored
) {
82 public boolean isRemote() {
87 public String
getObjectPath() {
93 final String number
, final boolean voiceVerification
94 ) throws Error
.Failure
, Error
.InvalidNumber
{
95 registerWithCaptcha(number
, voiceVerification
, null);
99 public void registerWithCaptcha(
100 final String number
, final boolean voiceVerification
, final String captcha
101 ) throws Error
.Failure
, Error
.InvalidNumber
{
102 if (!Manager
.isValidNumber(number
, null)) {
103 throw new SignalControl
.Error
.InvalidNumber(
104 "Invalid username (phone number), make sure you include the country code.");
106 try (final RegistrationManager registrationManager
= c
.getNewRegistrationManager(number
)) {
107 registrationManager
.register(voiceVerification
, captcha
);
108 } catch (CaptchaRequiredException e
) {
109 String message
= captcha
== null ?
"Captcha required for verification." : "Invalid captcha given.";
110 throw new SignalControl
.Error
.RequiresCaptcha(message
);
111 } catch (IOException e
) {
112 throw new SignalControl
.Error
.Failure(e
.getClass().getSimpleName() + " " + e
.getMessage());
117 public void verify(final String number
, final String verificationCode
) throws Error
.Failure
, Error
.InvalidNumber
{
118 verifyWithPin(number
, verificationCode
, null);
122 public void verifyWithPin(
123 final String number
, final String verificationCode
, final String pin
124 ) throws Error
.Failure
, Error
.InvalidNumber
{
125 try (final RegistrationManager registrationManager
= c
.getNewRegistrationManager(number
)) {
126 final Manager manager
= registrationManager
.verifyAccount(verificationCode
, pin
);
128 } catch (IOException
| PinLockedException
| IncorrectPinException e
) {
129 throw new SignalControl
.Error
.Failure(e
.getClass().getSimpleName() + " " + e
.getMessage());
134 public String
link(final String newDeviceName
) throws Error
.Failure
{
136 final ProvisioningManager provisioningManager
= c
.getNewProvisioningManager();
137 final URI deviceLinkUri
= provisioningManager
.getDeviceLinkUri();
140 final Manager manager
= provisioningManager
.finishDeviceLink(newDeviceName
);
142 } catch (IOException
| TimeoutException
| UserAlreadyExists e
) {
146 return deviceLinkUri
.toString();
147 } catch (TimeoutException
| IOException e
) {
148 throw new SignalControl
.Error
.Failure(e
.getClass().getSimpleName() + " " + e
.getMessage());
153 public String
version() {
154 return BaseConfig
.PROJECT_VERSION
;
158 public List
<DBusPath
> listAccounts() {
159 synchronized (receiveThreads
) {
160 return receiveThreads
.stream()
162 .map(Manager
::getSelfNumber
)
163 .map(u
-> new DBusPath(DbusConfig
.getObjectPath(u
)))
164 .collect(Collectors
.toList());