Skip to content

Commit

Permalink
fix: prevent infinite loop in readFromRadio function
Browse files Browse the repository at this point in the history
  • Loading branch information
danditomaso committed Jan 16, 2025
1 parent 715e35d commit 6c6326f
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 28 deletions.
52 changes: 26 additions & 26 deletions src/adapters/bleConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,34 +213,34 @@ export class BleConnection extends MeshDevice {
return await Promise.resolve(true);
}

/** Short description */
/**
* Reads data packets from the radio until empty
* @throws Error if reading fails
*/
protected async readFromRadio(): Promise<void> {
// if (this.pendingRead) {
// return Promise.resolve();
// }
// this.pendingRead = true;
let readBuffer = new ArrayBuffer(1);

while (readBuffer.byteLength > 0 && this.fromRadioCharacteristic) {
await this.fromRadioCharacteristic
.readValue()
.then((value) => {
readBuffer = value.buffer;

if (value.byteLength > 0) {
this.handleFromRadio(new Uint8Array(readBuffer));
}
this.updateDeviceStatus(Types.DeviceStatusEnum.DeviceConnected);
})
.catch((e: Error) => {
readBuffer = new ArrayBuffer(0);
this.log.error(
Types.Emitter[Types.Emitter.ReadFromRadio],
`❌ ${e.message}`,
);
});

try {
let hasMoreData = true;
while (hasMoreData && this.fromRadioCharacteristic) {
const value = await this.fromRadioCharacteristic.readValue();

if (value.byteLength === 0) {
hasMoreData = false;
continue;
}

await this.handleFromRadio(new Uint8Array(value.buffer));
this.updateDeviceStatus(Types.DeviceStatusEnum.DeviceConnected);
}
} catch (error) {
this.log.error(
Types.Emitter[Types.Emitter.ReadFromRadio],
`❌ ${error instanceof Error ? error.message : "Unknown error"}`,
);
throw error; // Re-throw to let caller handle
} finally {
// this.pendingRead = false;
}
// this.pendingRead = false;
}

/**
Expand Down
29 changes: 27 additions & 2 deletions src/utils/general.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,34 @@
/**
* Converts a `Uint8Array` to an `ArrayBuffer`
* Converts a Uint8Array to an ArrayBuffer efficiently, with additional safety checks.
* @param array - The Uint8Array to convert
* @returns A new ArrayBuffer containing the Uint8Array data
* @throws { TypeError } If input is not a Uint8Array
*/
export const typedArrayToBuffer = (array: Uint8Array): ArrayBuffer => {
if (!(array instanceof Uint8Array)) {
throw new TypeError("Input must be a Uint8Array");
}

if (array.byteLength === 0) {
return new ArrayBuffer(0);
}

// Check if the buffer is shared
if (array.buffer instanceof SharedArrayBuffer) {
// Always create a new buffer for shared memory
const newBuffer = new ArrayBuffer(array.byteLength);
new Uint8Array(newBuffer).set(array);
return newBuffer;
}

// If array uses the entire buffer and isn't offset, return it directly
if (array.byteOffset === 0 && array.byteLength === array.buffer.byteLength) {
return array.buffer;
}

// Otherwise, return a slice of the buffer containing just our data
return array.buffer.slice(
array.byteOffset,
array.byteLength + array.byteOffset,
array.byteOffset + array.byteLength,
);
};

0 comments on commit 6c6326f

Please sign in to comment.