const t = require("hypercore-crypto"),
i = require("safety-catch"),
e = require("signal-promise"),
{ createMemberProofJoinOperation: s } = require("../../invitations"),
{ Task: o } = require("../task"),
a = 12e4
module.exports = class extends o {
constructor(t) {
super(t)
const i = this.description.joinRoomKeys
;((this._keys = i.keys),
(this._isReadOnly = this._keys.status?.isReadOnly),
(this._identityInfo = null),
(this._writerInfo = null),
(this._roomInfo = null),
(this._roomPreferences = null),
(this._room = null),
(this._timer = null),
(this._signal = null),
(this._watcher = null),
(this._localWatcher = null))
}
_close() {
;(this._signal && this._signal.notify(new Error("Fast join closed before resolving digest")),
this._localWatcher && this.local.unwatch(this._localWatcher),
this._room && this.keet.internalReleaseRoom(this._room),
this._timer && clearTimeout(this._timer))
}
async _save() {
const t = await this.keet.internalEnterLocalTransaction()
try {
;(await t.insert("@local/writers", this._writerInfo), await t.flush())
} finally {
await this.keet.internalExitLocalTransaction()
}
}
async _appendJoinRequest() {
if (!(await this.keet.internalVerifyOptimisticCore(this._core)) || this.closing) return
const t = {
device: this.keet.internalCreateDeviceUpdate(this._identityInfo, this._core.key),
member: this.keet.internalGetMemberUpdate(this._identityInfo),
}
let i = null
i = this._keys.initiator
? this.keet.internalGetHeads(this._keys.initiator, this._room)
: [{ key: this._keys.roomKey, length: 1 }]
const e = s(this._keys.mailbox, t, { heads: i })
await this.keet.internalAppendOptimisticOperation(this._core.key, e)
}
async _openRoom() {
;((this._room = this.keet.internalOpenRoom(this._keys.roomKey, this._keys.encryptionKey, {
fastForwardTo: this._keys.fastForwardTo ? { key: this._keys.fastForwardTo } : null,
mailbox: this._keys.mailbox,
bigBatches: !!this._keys.identitySwap,
})),
await this._room.ready())
}
async _doRun() {
if (((this._identityInfo = await this.keet.internalGetIdentityInfo()), this.closing)) return
const [s, o, a] = await Promise.all([
this.local.get("@local/writers", { mailbox: this._keys.mailbox }),
this.local.get("@local/rooms", { roomKey: this._keys.roomKey }),
this.local.get("@local/room-preferences", { roomKey: this._keys.roomKey }),
])
;((this._writerInfo = s), (this._roomInfo = o), (this._roomPreferences = a))
let n = null
;(this._writerInfo
? (this._core = this.store.get(this._writerInfo.key))
: ((n = t.keyPair()), (this._core = this.store.get({ keyPair: n }))),
await this._core.ready(),
this.closing ||
(this._roomInfo && (await this._openRoom()),
this.closing ||
(this._writerInfo ||
(this._writerInfo = {
keyPair: n,
key: this._core.key,
mailbox: this._keys.mailbox,
responseKeyPair: null,
roomKey: null,
}),
(this._writerInfo.roomKey = this._keys.roomKey),
0 !== this._core.length || this._isReadOnly || (await this._appendJoinRequest()),
this.closing ||
(await this._save(),
this.closing ||
(this._room || (await this._openRoom()),
this._isReadOnly || (await this._room.base.setLocal(this._core.key)),
(this._signal = new e()),
(this._localWatcher = async () => {
try {
;(await this.local.get("@local/rooms", { roomKey: this._keys.roomKey })) &&
this._signal.notify()
} catch (t) {
i(t)
}
}),
this.local.watch(this._localWatcher),
this._localWatcher(),
await this._signal.wait())))))
}
_release() {
;(this.keet.debugRunningFastJoins--, this.keet.internalFastJoinSemaphore.signal())
}
async _run() {
;(await this.keet.internalFastJoinSemaphore.wait(),
this.keet.debugRunningFastJoins++,
(this.keet.debugMaxRunningFastJoins = Math.max(
this.keet.debugMaxRunningFastJoins,
this.keet.debugRunningFastJoins,
)))
try {
if (this.closing) return
;((this._timer = setTimeout(() => this._release(), a)), await this._doRun())
} finally {
this._release()
}
}
}