Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
if (e.errorCode === BleErrorCode.DeviceMTUChangeFailed) {
// eslint-disable-next-line require-atomic-updates
connectOptions = {};
await device.connect();
} else {
throw e;
}
}
}
await device.discoverAllServicesAndCharacteristics();
let res = retrieveInfos(device);
let characteristics;
if (!res) {
for (const uuid of getBluetoothServiceUuids()) {
try {
characteristics = await device.characteristicsForService(uuid);
res = getInfosForServiceUuid(uuid);
break;
} catch (e) {
// we attempt to connect to service
}
}
}
if (!res) {
throw new TransportError("service not found", "BLEServiceNotFound");
}
const { deviceModel, serviceUuid, writeUuid, notifyUuid } = res;
if (!characteristics) {
}
log("ble-verbose", `open(${deviceOrId})`);
await awaitsBleOn(bleManager);
if (!device) {
// works for iOS but not Android
const devices = await bleManager.devices([deviceOrId]);
log("ble-verbose", `found ${devices.length} devices`);
[device] = devices;
}
if (!device) {
const connectedDevices = await bleManager.connectedDevices(
getBluetoothServiceUuids()
);
const connectedDevicesFiltered = connectedDevices.filter(
d => d.id === deviceOrId
);
log(
"ble-verbose",
`found ${connectedDevicesFiltered.length} connected devices`
);
[device] = connectedDevicesFiltered;
}
if (!device) {
log("ble-verbose", `connectToDevice(${deviceOrId})`);
try {
device = await bleManager.connectToDevice(deviceOrId, connectOptions);
} catch (e) {
await device.connect();
} else {
throw e;
}
}
}
await device.discoverAllServicesAndCharacteristics();
let res = retrieveInfos(device);
let characteristics;
if (!res) {
for (const uuid of getBluetoothServiceUuids()) {
try {
characteristics = await device.characteristicsForService(uuid);
res = getInfosForServiceUuid(uuid);
break;
} catch (e) {
// we attempt to connect to service
}
}
}
if (!res) {
throw new TransportError("service not found", "BLEServiceNotFound");
}
const { deviceModel, serviceUuid, writeUuid, notifyUuid } = res;
if (!characteristics) {
characteristics = await device.characteristicsForService(serviceUuid);
}
this.exchangeAtomicImpl(async () => {
try {
const msgIn = apdu.toString("hex");
log("apdu", `=> ${msgIn}`);
const data = await merge(
this.notifyObservable.pipe(receiveAPDU),
sendAPDU(this.write, apdu, this.mtuSize)
).toPromise();
const msgOut = data.toString("hex");
log("apdu", `<= ${msgOut}`);
return data;
} catch (e) {
log("ble-error", "exchange got " + String(e));
if (this.notYetDisconnected) {
// in such case we will always disconnect because something is bad.
this.device.gatt.disconnect();
}
throw e;
}
});
this.exchangeAtomicImpl(async () => {
try {
const msgIn = apdu.toString("hex");
log("apdu", `=> ${msgIn}`);
const data = await merge(
this.notifyObservable.pipe(receiveAPDU),
sendAPDU(this.write, apdu, this.mtuSize)
).toPromise();
const msgOut = data.toString("hex");
log("apdu", `<= ${msgOut}`);
return data;
} catch (e) {
log("ble-error", "exchange got " + String(e));
if (this.notYetDisconnected) {
// in such case we will always disconnect because something is bad.
await bleManager.cancelDeviceConnection(this.id).catch(() => {}); // but we ignore if disconnect worked.
}
throw remapError(e);
}
});
this.exchangeAtomicImpl(async () => {
try {
const msgIn = apdu.toString("hex");
log("apdu", `=> ${msgIn}`);
const data = await merge(
this.notifyObservable.pipe(receiveAPDU),
sendAPDU(this.write, apdu, this.mtuSize)
).toPromise();
const msgOut = data.toString("hex");
log("apdu", `<= ${msgOut}`);
return data;
} catch (e) {
log("ble-error", "exchange got " + String(e));
if (this.notYetDisconnected) {
// in such case we will always disconnect because something is bad.
await disconnectDevice(this.device).catch(() => {}); // but we ignore if disconnect worked.
}
throw e;
}
});
this.exchangeAtomicImpl(async () => {
const { channel, packetSize } = this;
log("apdu", "=> " + apdu.toString("hex"));
const framing = hidFraming(channel, packetSize);
// Write...
const blocks = framing.makeBlocks(apdu);
for (let i = 0; i < blocks.length; i++) {
log("hid-frame", "=> " + blocks[i].toString("hex"));
await this.writeHID(blocks[i]);
}
// Read...
let result;
let acc;
while (!(result = framing.getReducedResult(acc))) {
const buffer = await this.readHID();
log("hid-frame", "<= " + buffer.toString("hex"));
acc = framing.reduceResponse(acc, buffer);
}
this.exchangeAtomicImpl(async () => {
const { channel, packetSize } = this;
log("apdu", "=> " + apdu.toString("hex"));
const framing = hidFraming(channel, packetSize);
// Write...
const blocks = framing.makeBlocks(apdu);
for (let i = 0; i < blocks.length; i++) {
log("hid-frame", "=> " + blocks[i].toString("hex"));
await this.device.sendReport(0, blocks[i]);
}
// Read...
let result;
let acc;
while (!(result = framing.getReducedResult(acc))) {
const buffer = await this.read();
log("hid-frame", "<= " + buffer.toString("hex"));
acc = framing.reduceResponse(acc, buffer);
}
this.exchangeAtomicImpl(async () => {
const { channel, packetSize } = this;
log("apdu", "=> " + apdu.toString("hex"));
const framing = hidFraming(channel, packetSize);
// Write...
const blocks = framing.makeBlocks(apdu);
for (let i = 0; i < blocks.length; i++) {
log("hid-frame", "=> " + blocks[i].toString("hex"));
await this.device.transferOut(endpointNumber, blocks[i]);
}
// Read...
let result;
let acc;
while (!(result = framing.getReducedResult(acc))) {
const r = await this.device.transferIn(endpointNumber, packetSize);
const buffer = Buffer.from(r.data.buffer);
log("hid-frame", "<= " + buffer.toString("hex"));
acc = framing.reduceResponse(acc, buffer);
if (!navigator.credentials) {
throw new TransportError("WebAuthn not supported", "NotSupported");
}
return (
navigator.credentials
// $FlowFixMe
.get({
publicKey: {
timeout,
challenge: new Uint8Array(32),
allowCredentials: [
{
type: "public-key",
id: new Uint8Array(wrapApdu(apdu, scrambleKey))
}
]
}
})
// $FlowFixMe
.then(r => Buffer.from(r.response.signature))
);
};