mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-29 10:30:38 +00:00
Move receive thread handling to manager
This commit is contained in:
parent
5c389c875d
commit
fc0a9b4102
5 changed files with 156 additions and 49 deletions
|
@ -193,6 +193,20 @@ public interface Manager extends Closeable {
|
|||
|
||||
void requestAllSyncData() throws IOException;
|
||||
|
||||
/**
|
||||
* Add a handler to receive new messages.
|
||||
* Will start receiving messages from server, if not already started.
|
||||
*/
|
||||
void addReceiveHandler(ReceiveMessageHandler handler);
|
||||
|
||||
/**
|
||||
* Remove a handler to receive new messages.
|
||||
* Will stop receiving messages from server, if this was the last registered receiver.
|
||||
*/
|
||||
void removeReceiveHandler(ReceiveMessageHandler handler);
|
||||
|
||||
boolean isReceiving();
|
||||
|
||||
/**
|
||||
* Receive new messages from server, returns if no new message arrive in a timespan of timeout.
|
||||
*/
|
||||
|
|
|
@ -137,6 +137,10 @@ public class ManagerImpl implements Manager {
|
|||
private boolean hasCaughtUpWithOldMessages = false;
|
||||
private boolean ignoreAttachments = false;
|
||||
|
||||
private Thread receiveThread;
|
||||
private final Set<ReceiveMessageHandler> messageHandlers = new HashSet<>();
|
||||
private boolean isReceivingSynchronous;
|
||||
|
||||
ManagerImpl(
|
||||
SignalAccount account,
|
||||
PathConfig pathConfig,
|
||||
|
@ -872,6 +876,88 @@ public class ManagerImpl implements Manager {
|
|||
return actions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addReceiveHandler(final ReceiveMessageHandler handler) {
|
||||
if (isReceivingSynchronous) {
|
||||
throw new IllegalStateException("Already receiving message synchronously.");
|
||||
}
|
||||
synchronized (messageHandlers) {
|
||||
messageHandlers.add(handler);
|
||||
|
||||
startReceiveThreadIfRequired();
|
||||
}
|
||||
}
|
||||
|
||||
private void startReceiveThreadIfRequired() {
|
||||
if (receiveThread != null) {
|
||||
return;
|
||||
}
|
||||
receiveThread = new Thread(() -> {
|
||||
while (!Thread.interrupted()) {
|
||||
try {
|
||||
receiveMessagesInternal(1L, TimeUnit.HOURS, false, (envelope, decryptedContent, e) -> {
|
||||
synchronized (messageHandlers) {
|
||||
for (ReceiveMessageHandler h : messageHandlers) {
|
||||
try {
|
||||
h.handleMessage(envelope, decryptedContent, e);
|
||||
} catch (Exception ex) {
|
||||
logger.warn("Message handler failed, ignoring", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
} catch (IOException e) {
|
||||
logger.warn("Receiving messages failed, retrying", e);
|
||||
}
|
||||
}
|
||||
hasCaughtUpWithOldMessages = false;
|
||||
synchronized (messageHandlers) {
|
||||
receiveThread = null;
|
||||
|
||||
// Check if in the meantime another handler has been registered
|
||||
if (!messageHandlers.isEmpty()) {
|
||||
startReceiveThreadIfRequired();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
receiveThread.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeReceiveHandler(final ReceiveMessageHandler handler) {
|
||||
final Thread thread;
|
||||
synchronized (messageHandlers) {
|
||||
thread = receiveThread;
|
||||
receiveThread = null;
|
||||
messageHandlers.remove(handler);
|
||||
if (!messageHandlers.isEmpty() || isReceivingSynchronous) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
stopReceiveThread(thread);
|
||||
}
|
||||
|
||||
private void stopReceiveThread(final Thread thread) {
|
||||
thread.interrupt();
|
||||
try {
|
||||
thread.join();
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReceiving() {
|
||||
if (isReceivingSynchronous) {
|
||||
return true;
|
||||
}
|
||||
synchronized (messageHandlers) {
|
||||
return messageHandlers.size() > 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveMessages(long timeout, TimeUnit unit, ReceiveMessageHandler handler) throws IOException {
|
||||
receiveMessages(timeout, unit, true, handler);
|
||||
|
@ -884,6 +970,23 @@ public class ManagerImpl implements Manager {
|
|||
|
||||
private void receiveMessages(
|
||||
long timeout, TimeUnit unit, boolean returnOnTimeout, ReceiveMessageHandler handler
|
||||
) throws IOException {
|
||||
if (isReceiving()) {
|
||||
throw new IllegalStateException("Already receiving message.");
|
||||
}
|
||||
isReceivingSynchronous = true;
|
||||
receiveThread = Thread.currentThread();
|
||||
try {
|
||||
receiveMessagesInternal(timeout, unit, returnOnTimeout, handler);
|
||||
} finally {
|
||||
receiveThread = null;
|
||||
hasCaughtUpWithOldMessages = false;
|
||||
isReceivingSynchronous = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void receiveMessagesInternal(
|
||||
long timeout, TimeUnit unit, boolean returnOnTimeout, ReceiveMessageHandler handler
|
||||
) throws IOException {
|
||||
retryFailedReceivedMessages(handler);
|
||||
|
||||
|
@ -1249,6 +1352,15 @@ public class ManagerImpl implements Manager {
|
|||
}
|
||||
|
||||
private void close(boolean closeAccount) throws IOException {
|
||||
Thread thread;
|
||||
synchronized (messageHandlers) {
|
||||
messageHandlers.clear();
|
||||
thread = receiveThread;
|
||||
receiveThread = null;
|
||||
}
|
||||
if (thread != null) {
|
||||
stopReceiveThread(thread);
|
||||
}
|
||||
executor.shutdown();
|
||||
|
||||
dependencies.getSignalWebSocket().disconnect();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue