OverviewFilesCommitsIssuesDocsReleasesPeers

keet-cli / keet-core-4.14.4-pretty / lib / core / tasks / pairing / keys.js

120 lines · javascript ref:
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()
    }
  }
}