Skip to content

Commit 5f214af

Browse files
committed
Reconnect to KeePassXC in case connection was lost
1 parent 56d7be5 commit 5f214af

File tree

1 file changed

+39
-2
lines changed

1 file changed

+39
-2
lines changed

src/main/java/org/keepassxc/Connection.java

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import java.nio.charset.StandardCharsets;
1616
import java.util.*;
1717
import java.util.concurrent.*;
18+
import java.util.concurrent.atomic.AtomicReference;
1819

1920
/**
2021
* Establishes a connection to KeePassXC via its build-in proxy.
@@ -32,9 +33,13 @@ public abstract class Connection implements AutoCloseable {
3233
private byte[] nonce;
3334

3435
final ExecutorService executorService = Executors.newFixedThreadPool(2);
35-
final MessagePublisher messagePublisher = new MessagePublisher();
36+
protected MessagePublisher messagePublisher;
3637
private final ConcurrentLinkedQueue<JSONObject> queue = new ConcurrentLinkedQueue<>();
3738

39+
private final int MAX_ERROR_COUNT = 4;
40+
private final int RECONNECT_DELAY_S = 15;
41+
private final AtomicReference<ScheduledFuture<?>> scheduledConnectCmd = new AtomicReference<>();
42+
3843
private final long RESPONSE_DELAY_MS = 500;
3944
private final ScheduledExecutorService scheduler;
4045

@@ -56,6 +61,7 @@ public Connection() {
5661

5762
class MessagePublisher implements Runnable {
5863
private boolean doStop = false;
64+
private int errorCount = 0;
5965

6066
public synchronized void doStop() {
6167
this.doStop = true;
@@ -68,7 +74,18 @@ private synchronized boolean keepRunning() {
6874
@Override
6975
public void run() {
7076
while (keepRunning()) {
71-
queue.offer(getCleartextResponse());
77+
var response = getCleartextResponse();
78+
if (!response.isEmpty()) {
79+
queue.offer(response);
80+
errorCount = 0;
81+
} else {
82+
errorCount++;
83+
if (errorCount > MAX_ERROR_COUNT) {
84+
log.info("Too much errors - stopping MessagePublisher");
85+
doStop();
86+
reconnect();
87+
}
88+
}
7289
}
7390
log.debug("MessagePublisher stopped");
7491
}
@@ -108,10 +125,30 @@ public JSONObject call() throws Exception {
108125
}
109126

110127
void lauchMessagePublisher() {
128+
messagePublisher = new MessagePublisher();
111129
log.debug("MessagePublisher started");
112130
executorService.execute(messagePublisher);
113131
}
114132

133+
/**
134+
* Tries to reconnect after a configured time in case connection to KeePassXC was lost.
135+
* It keeps on trying until a new connection could be established.
136+
*/
137+
private void reconnect() {
138+
Runnable connect = () -> {
139+
try {
140+
this.connect();
141+
} catch (IOException e) {
142+
reconnect();
143+
}
144+
};
145+
var scheduledTask = scheduler.schedule(connect, RECONNECT_DELAY_S, TimeUnit.SECONDS);
146+
var previouslyScheduledTask = scheduledConnectCmd.getAndSet(scheduledTask);
147+
if (previouslyScheduledTask != null) {
148+
previouslyScheduledTask.cancel(false);
149+
}
150+
}
151+
115152
public void addPropertyChangeListener(PropertyChangeListener pcl) {
116153
support.addPropertyChangeListener(pcl);
117154
}

0 commit comments

Comments
 (0)