Skip to content

Commit

Permalink
!wip
Browse files Browse the repository at this point in the history
  • Loading branch information
valpinkman committed Dec 31, 2024
1 parent ff65f9e commit a899e28
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,18 @@ 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) => {
console.log("sendApduUseCase:Got error", _error);
this.updateDeviceStatus(DeviceStatus.CONNECTED);
}
});
});
}

async sendCommand<Response, Args, ErrorStatusCodes>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -35,6 +35,7 @@ export class WebHidDeviceConnection implements DeviceConnection {
private readonly _apduReceiver: ApduReceiverService;
private _sendApduSubject: Subject<ApduResponse> = new Subject();
private readonly _logger: LoggerPublisherService;
private _pendingApdu: Maybe<Uint8Array> = Nothing;

/** Callback to notify the connection termination */
private _onConnectionTerminated: () => void;
Expand Down Expand Up @@ -80,7 +81,7 @@ export class WebHidDeviceConnection implements DeviceConnection {
triggersDisconnection?: boolean,
): Promise<Either<DmkError, ApduResponse>> {
this._sendApduSubject = new Subject();

this._pendingApdu = Maybe.of(apdu);
this._logger.debug("Sending APDU", {
data: { apdu },
tag: "apdu-sender",
Expand All @@ -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({
Expand All @@ -102,14 +111,30 @@ 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("sendApdu:Waiting for reconnection", {
data: { waitingForReconnection: this.waitingForReconnection },
});
this._logger.info("sendApdu:Device opened", {
data: { opened: this.device.opened },
});

if (this.waitingForReconnection || !this.device.opened) {
const reconnectionRes = await this.waitForReconnection();
this._logger.info("sendApdu:Waiting for reconnection");
const waitingForDeviceResponse =
this.device.opened && this._pendingApdu.isJust();

const reconnectionRes = await this.waitForReconnection(
waitingForDeviceResponse,
);

if (reconnectionRes.isLeft()) {
return reconnectionRes;
}
Expand Down Expand Up @@ -154,12 +179,37 @@ export class WebHidDeviceConnection implements DeviceConnection {
});
}

private waitForReconnection(): Promise<Either<DmkError, void>> {
if (this.terminated)
private waitForReconnection(
waitingForDeviceResponse: boolean = false,
): Promise<Either<DmkError, void>> {
this._logger.info("waitForReconnection:Started", {
data: { waitingForDeviceResponse },
});
if (this.terminated) {
return Promise.resolve(Left(new ReconnectionFailedError()));
}

return new Promise<Either<DmkError, void>>((resolve) => {
const sub = this.reconnectionSubject.subscribe({
next: (res) => {
next: async (res) => {
this._logger.info("waitForReconnection:Waiting for device response", {
data: {
waitingForDeviceResponse,
pendingApdu: this._pendingApdu.extract(),
},
});

if (waitingForDeviceResponse) {
this._sendApduSubject.error(new WebHidSendReportError());
}

if (this._pendingApdu.isJust()) {
this._logger.info(
"waitForReconnection:Pending apdu is just, resending APDU",
);
await this.sendApdu(this._pendingApdu.extract());
}

if (res === "success") {
resolve(Right(undefined));
} else {
Expand Down

0 comments on commit a899e28

Please sign in to comment.