From 76a2469031f136c3ef1115aa21c27f9981afe1ec Mon Sep 17 00:00:00 2001 From: "Valentin D. Pinkman" Date: Mon, 30 Dec 2024 14:48:35 +0100 Subject: [PATCH] !wip --- .../device-session/model/DeviceSession.ts | 16 ++++--- .../api/transport/WebHidDeviceConnection.ts | 47 +++++++++++++++++-- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/packages/device-management-kit/src/internal/device-session/model/DeviceSession.ts b/packages/device-management-kit/src/internal/device-session/model/DeviceSession.ts index 0b9d22996..8435448d7 100644 --- a/packages/device-management-kit/src/internal/device-session/model/DeviceSession.ts +++ b/packages/device-management-kit/src/internal/device-session/model/DeviceSession.ts @@ -120,13 +120,17 @@ export class DeviceSession { options.triggersDisconnection, ); - return errorOrResponse.ifRight((response: ApduResponse) => { - if (CommandUtils.isLockedDeviceResponse(response)) { - this.updateDeviceStatus(DeviceStatus.LOCKED); - } else { + return errorOrResponse + .ifRight((response: ApduResponse) => { + if (CommandUtils.isLockedDeviceResponse(response)) { + this.updateDeviceStatus(DeviceStatus.LOCKED); + } else { + this.updateDeviceStatus(DeviceStatus.CONNECTED); + } + }) + .ifLeft((_error) => { this.updateDeviceStatus(DeviceStatus.CONNECTED); - } - }); + }); } async sendCommand( diff --git a/packages/transport/web-hid/src/api/transport/WebHidDeviceConnection.ts b/packages/transport/web-hid/src/api/transport/WebHidDeviceConnection.ts index 1fb09cea9..089310d27 100644 --- a/packages/transport/web-hid/src/api/transport/WebHidDeviceConnection.ts +++ b/packages/transport/web-hid/src/api/transport/WebHidDeviceConnection.ts @@ -9,7 +9,7 @@ import { type LoggerPublisherService, ReconnectionFailedError, } from "@ledgerhq/device-management-kit"; -import { type Either, Left, Right } from "purify-ts"; +import { type Either, Left, Maybe, Nothing, Right } from "purify-ts"; import { Subject } from "rxjs"; import { RECONNECT_DEVICE_TIMEOUT } from "@api/data/WebHidConfig"; @@ -35,6 +35,7 @@ export class WebHidDeviceConnection implements DeviceConnection { private readonly _apduReceiver: ApduReceiverService; private _sendApduSubject: Subject = new Subject(); private readonly _logger: LoggerPublisherService; + private _pendingApdu: Maybe = Nothing; /** Callback to notify the connection termination */ private _onConnectionTerminated: () => void; @@ -80,7 +81,7 @@ export class WebHidDeviceConnection implements DeviceConnection { triggersDisconnection?: boolean, ): Promise> { this._sendApduSubject = new Subject(); - + this._pendingApdu = Maybe.of(apdu); this._logger.debug("Sending APDU", { data: { apdu }, tag: "apdu-sender", @@ -90,7 +91,15 @@ export class WebHidDeviceConnection implements DeviceConnection { (resolve) => { this._sendApduSubject.subscribe({ next: async (r) => { + this._logger.info("Received APDU Response", { + data: { response: r }, + }); + this._pendingApdu = Nothing; + this._logger.info("Next: Setting pending apdu to Nothing"); if (triggersDisconnection && CommandUtils.isSuccessResponse(r)) { + this._logger.info( + "Triggers disconnection, waiting for reconnection", + ); // Anticipate the disconnection and wait for the reconnection before resolving const reconnectionRes = await this.waitForReconnection(); reconnectionRes.caseOf({ @@ -102,14 +111,29 @@ export class WebHidDeviceConnection implements DeviceConnection { } }, error: (err) => { + this._pendingApdu = Nothing; + this._logger.info("Error: Setting pending apdu to Nothing"); resolve(Left(err)); }, }); }, ); + this._logger.info("Waiting for reconnection", { + data: { waitingForReconnection: this.waitingForReconnection }, + }); + this._logger.info("Device opened", { + data: { opened: this.device.opened }, + }); + if (this.waitingForReconnection || !this.device.opened) { - const reconnectionRes = await this.waitForReconnection(); + const waitingForDeviceResponse = + this.device.opened && this._pendingApdu.isJust(); + + const reconnectionRes = await this.waitForReconnection( + waitingForDeviceResponse, + ); + if (reconnectionRes.isLeft()) { return reconnectionRes; } @@ -154,12 +178,25 @@ export class WebHidDeviceConnection implements DeviceConnection { }); } - private waitForReconnection(): Promise> { - if (this.terminated) + private waitForReconnection( + waitingForDeviceResponse: boolean = false, + ): Promise> { + if (this.terminated) { return Promise.resolve(Left(new ReconnectionFailedError())); + } + return new Promise>((resolve) => { const sub = this.reconnectionSubject.subscribe({ next: (res) => { + if (waitingForDeviceResponse) { + if (this._pendingApdu.isJust()) { + this._logger.info("Pending apdu is just, resending APDU"); + this.sendApdu(this._pendingApdu.extract()); + } else { + this._sendApduSubject.error(new WebHidSendReportError()); + } + } + if (res === "success") { resolve(Right(undefined)); } else {