aboutsummaryrefslogtreecommitdiff
path: root/xP
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2025-05-09 22:34:25 +0200
committerPřemysl Eric Janouch <p@janouch.name>2025-05-10 12:08:51 +0200
commit7ba17a016140f578bccca3ffd320c1663cf66c6c (patch)
treeac6404da3f3745c46c962547b2b56105802b8513 /xP
parent4cf8c394b9b07d4bab2ea297edcfeb566af8e28f (diff)
downloadxK-7ba17a016140f578bccca3ffd320c1663cf66c6c.tar.gz
xK-7ba17a016140f578bccca3ffd320c1663cf66c6c.tar.xz
xK-7ba17a016140f578bccca3ffd320c1663cf66c6c.zip
Make the relay acknowledge all received commands
To that effect, bump liberty and the xC relay protocol version. Relay events have been reordered to improve forward compatibility. Also prevent use-after-free when serialization fails. xP now slightly throttles activity notifications, and indicates when there are unacknowledged commands.
Diffstat (limited to 'xP')
-rw-r--r--xP/public/xP.js46
1 files changed, 37 insertions, 9 deletions
diff --git a/xP/public/xP.js b/xP/public/xP.js
index 6035db3..33d7d2a 100644
--- a/xP/public/xP.js
+++ b/xP/public/xP.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2022 - 2024, Přemysl Eric Janouch <p@janouch.name>
+// Copyright (c) 2022 - 2025, Přemysl Eric Janouch <p@janouch.name>
// SPDX-License-Identifier: 0BSD
import * as Relay from './proto.js'
@@ -67,18 +67,19 @@ class RelayRPC extends EventTarget {
_processOne(message) {
let e = message.data
+ let p
switch (e.event) {
case Relay.Event.Error:
- if (this.promised[e.commandSeq] !== undefined)
- this.promised[e.commandSeq].reject(e.error)
- else
+ if ((p = this.promised[e.commandSeq]) === undefined)
console.error(`Unawaited error: ${e.error}`)
+ else if (p !== true)
+ p.reject(e.error)
break
case Relay.Event.Response:
- if (this.promised[e.commandSeq] !== undefined)
- this.promised[e.commandSeq].resolve(e.data)
- else
+ if ((p = this.promised[e.commandSeq]) === undefined)
console.error("Unawaited response")
+ else if (p !== true)
+ p.resolve(e.data)
break
default:
e.eventSeq = message.eventSeq
@@ -95,6 +96,13 @@ class RelayRPC extends EventTarget {
this.promised[seq].reject("No response")
delete this.promised[seq]
}
+ m.redraw()
+ }
+
+ get busy() {
+ for (const seq in this.promised)
+ return true
+ return false
}
send(params) {
@@ -110,6 +118,9 @@ class RelayRPC extends EventTarget {
this.ws.send(JSON.stringify({commandSeq: seq, data: params}))
+ this.promised[seq] = true
+ m.redraw()
+
// Automagically detect if we want a result.
let data = undefined
const promise = new Promise(
@@ -191,6 +202,17 @@ let bufferAutoscroll = true
let servers = new Map()
+let lastActive = undefined
+
+function notifyActive() {
+ // Reduce unnecessary traffic.
+ const now = Date.now()
+ if (lastActive === undefined || (now - lastActive >= 5000)) {
+ lastActive = now
+ rpc.send({command: 'Active'})
+ }
+}
+
function bufferResetStats(b) {
b.newMessages = 0
b.newUnimportantMessages = 0
@@ -998,7 +1020,7 @@ let Input = {
onKeyDown: event => {
// TODO: And perhaps on other actions, too.
- rpc.send({command: 'Active'})
+ notifyActive()
let b = buffers.get(bufferCurrent)
if (b === undefined || event.isComposing)
@@ -1103,7 +1125,13 @@ let Main = {
return m('.xP', {}, [
overlay,
- m('.title', {}, [m('b', {}, `xP`), m(Topic)]),
+ m('.title', {}, [
+ m('span', [
+ rpc.busy ? '⋯ ' : undefined,
+ m('b', {}, `xP`),
+ ]),
+ m(Topic),
+ ]),
m('.middle', {}, [m(BufferList), m(BufferContainer)]),
m(Status),
m('.input', {}, [m(Prompt), m(Input)]),