Re-work waiting for auth

This commit is contained in:
Jon Staab
2024-11-05 14:17:04 -08:00
parent ecb08cace9
commit 0ec2b6ec73
6 changed files with 50 additions and 47 deletions
+1 -5
View File
@@ -39,17 +39,13 @@ export class Connection extends Emitter {
emit = (type: ConnectionEvent, ...args: any[]) => super.emit(type, this, ...args)
send = async (message: Message) => {
await this.open()
await this.socket.open()
if (this.status === Ready) {
this.sender.push(message)
}
}
open = async () => {
await this.socket.open()
}
close = async () => {
this.status = Closing
+32 -29
View File
@@ -37,9 +37,10 @@ export class ConnectionAuth {
constructor(readonly cxn: Connection) {
this.cxn.on(ConnectionEvent.Close, this.#onClose)
this.cxn.on(ConnectionEvent.Receive, this.#onReceive)
}
#onMessage = (cxn: Connection, [verb, ...extra]: Message) => {
#onReceive = (cxn: Connection, [verb, ...extra]: Message) => {
if (verb === 'OK') {
const [id, ok, message] = extra
@@ -56,7 +57,7 @@ export class ConnectionAuth {
this.status = Requested
if (ctx.net.authMode === AuthMode.Implicit) {
this.attempt()
this.respond()
}
}
}
@@ -68,7 +69,25 @@ export class ConnectionAuth {
this.status = None
}
attempt = async () => {
waitFor = async (condition: () => boolean, timeout = 300) => {
const start = Date.now()
while (Date.now() - timeout <= start) {
await sleep(100)
if (condition()) {
break
}
}
}
waitForChallenge = async (timeout = 300) =>
this.waitFor(() => Boolean(this.challenge), timeout)
waitForResolution = async (timeout = 300) =>
this.waitFor(() => [None, DeniedSignature, Forbidden, Ok].includes(this.status), timeout)
respond = async () => {
if (!this.challenge) {
throw new Error("Attempted to authenticate with no challenge")
}
@@ -86,7 +105,10 @@ export class ConnectionAuth {
],
})
const [event] = await Promise.all([ctx.net.signEvent(template), this.cxn.open()])
const [event] = await Promise.all([
ctx.net.signEvent(template),
this.cxn.socket.open(),
])
if (event) {
this.request = event.id
@@ -97,33 +119,14 @@ export class ConnectionAuth {
}
}
attemptIfRequested = async () => {
attempt = async (timeout = 300) => {
await this.cxn.socket.open()
await this.waitForChallenge(timeout)
if (this.status === Requested) {
await this.attempt()
await this.respond()
}
}
wait = async ({timeout = 3000}: {timeout?: number} = {}) => {
const deadline = Date.now() + timeout
while (Date.now() < deadline) {
await sleep(100)
// State got reset while we were waiting
if ([None, Requested].includes(this.status)) {
break
}
// We've completed the auth flow
if ([DeniedSignature, Forbidden, Ok].includes(this.status)) {
break
}
}
}
waitIfPending = async ({timeout = 3000}: {timeout?: number} = {}) => {
while ([PendingSignature, PendingResponse].includes(this.status)) {
await this.wait({timeout})
}
await this.waitForResolution(timeout)
}
}
+7
View File
@@ -63,9 +63,16 @@ export class Socket {
}
close = async () => {
if (this.cxn.url === 'wss://filter.nostr.wine/') {
console.trace('closing')
}
this.worker.pause()
this.ws?.close()
// Allow the socket to start closing before waiting
await sleep(100)
// Wait for the socket to fully clos
await this.wait()
this.ws = undefined
+1 -3
View File
@@ -300,10 +300,8 @@ const _executeSubscription = (sub: Subscription) => {
if (filters.length > 0) {
Promise.all(
executor.target.connections.map(async (connection: Connection) => {
await connection.open()
if (authTimeout) {
await connection.auth.waitIfPending({timeout: authTimeout})
await connection.auth.attempt(authTimeout)
}
})
).then(() => {