Skip to content

Commit b4a11ad

Browse files
committed
Rework and improve connection handling with KeePassXC backend
1 parent 00a2be6 commit b4a11ad

File tree

1 file changed

+30
-19
lines changed

1 file changed

+30
-19
lines changed

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

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@ public abstract class Connection implements AutoCloseable {
3232
private static final int nonceLength = 24;
3333
private byte[] nonce;
3434

35-
final ExecutorService executorService = Executors.newFixedThreadPool(2);
35+
final ExecutorService executorService = Executors.newFixedThreadPool(12);
3636
protected MessagePublisher messagePublisher;
37+
private final long QUEUE_CHECKING_INTERVAL_MS = 100;
38+
private final long SLOW_QUEUE_PROCESSING_MS = 500;
3739
private final ConcurrentLinkedQueue<JSONObject> queue = new ConcurrentLinkedQueue<>();
3840

3941
private final int MAX_ERROR_COUNT = 4;
@@ -76,6 +78,7 @@ public void run() {
7678
while (keepRunning()) {
7779
var response = getCleartextResponse();
7880
if (!response.isEmpty()) {
81+
if (!isSignal(response)) log.trace("Response added to queue: {}", response);
7982
queue.offer(response);
8083
errorCount = 0;
8184
} else {
@@ -105,13 +108,25 @@ public JSONObject call() throws Exception {
105108
while (true) {
106109
var response = queue.peek();
107110
if (null == response) {
108-
Thread.sleep(200);
111+
Thread.sleep(QUEUE_CHECKING_INTERVAL_MS);
109112
continue;
110113
}
111-
if (response.has("error")) break;
112-
var qit = queue.iterator();
113-
while (qit.hasNext()) {
114-
var message = qit.next();
114+
if (isSignal(response)) {
115+
queue.remove(response);
116+
continue;
117+
}
118+
if (response.toString().equals("{}")) {
119+
queue.remove(response);
120+
log.trace("KeePassXC send an empty response: {}", response);
121+
continue;
122+
}
123+
for (JSONObject message : queue) {
124+
log.trace("Checking in queue message {}, looking for action '{}' and nonce {}", message, action, b64encode(incrementNonce(nonce)));
125+
if (message.has("error") && message.getString("action").equals(action)) {
126+
queue.remove(message);
127+
log.trace("Found in and retrieved from queue: {}", message);
128+
return message;
129+
}
115130
if (message.has("action")
116131
&& message.getString("action").equals(action)
117132
&& message.has("nonce")
@@ -121,19 +136,8 @@ public JSONObject call() throws Exception {
121136
return message;
122137
}
123138
}
124-
if (isSignal(response)) {
125-
queue.poll();
126-
continue;
127-
}
128-
if (response.toString().equals("{}")) {
129-
queue.poll();
130-
log.trace("KeePassXC send an empty response: {}", response);
131-
continue;
132-
}
133-
log.trace("Response added to queue: {}", response);
139+
Thread.sleep(SLOW_QUEUE_PROCESSING_MS);
134140
}
135-
log.trace("Retrieved from queue: {}", queue.peek());
136-
return queue.poll();
137141
}
138142
}
139143

@@ -263,7 +267,14 @@ private synchronized JSONObject getEncryptedResponseAndDecrypt(String action, by
263267
var response = new JSONObject();
264268

265269
try {
266-
response = executorService.submit(new MessageConsumer(action, nonce)).get();
270+
// associate requires user input, other requests don't
271+
if (action.equals("associate")) {
272+
response = executorService.submit(new MessageConsumer(action, nonce)).get();
273+
} else {
274+
response = executorService.submit(new MessageConsumer(action, nonce)).get(1, TimeUnit.SECONDS);
275+
}
276+
} catch (TimeoutException toe) {
277+
throw new KeepassProxyAccessException("Timeout for action '" + action + "'");
267278
} catch (InterruptedException | ExecutionException e) {
268279
log.error(e.toString(), e.getCause());
269280
}

0 commit comments

Comments
 (0)