show packet error stats

This commit is contained in:
Lewis Moten
2024-05-14 20:43:48 -04:00
parent da7feaf09e
commit c4a0d8afd1
8 changed files with 333 additions and 47 deletions

View File

@@ -7,14 +7,24 @@ import {
bytesToBits,
numberToBytes,
numberToHex,
numberToAscii
numberToAscii,
bytesToNumber
} from "./converters";
const dispatcher = new Dispatcher('StreamManager', ['change']);
const dispatcher = new Dispatcher('StreamManager', [
'change',
'packetReceived',
'packetFailed',
'sizeReceived'
]);
let DATA = new Uint8ClampedArray();
const FAILED_SEQUENCES = [];
let FAILED_SEQUENCES = [];
let SUCCESS_SEQUENCES = [];
let SAMPLES_EXPECTED = 0;
let SAMPLES_RECEIVED = 0;
let DATA_CRC_BIT_COUNT = 0;
let DATA_SIZE_BIT_COUNT = 0;
let DATA_SIZE_CRC_BIT_COUNT = 0;
const BITS = [];
let BITS_PER_PACKET = 0;
@@ -29,10 +39,20 @@ let PACKET_ENCODING = {
export const addEventListener = dispatcher.addListener;
export const removeEventListener = dispatcher.removeListener;
const isPacketInRange = (packetIndex) => {
// Blindly accept. We can't do anything about it for now
if(!isSizeTrusted()) return true;
const { packetCount } = PacketUtils.packetStats(getSize());
return packetIndex < packetCount;
}
export const reset = () => {
let changed = false;
SAMPLES_RECEIVED = 0;
SAMPLES_EXPECTED = 0;
if(SUCCESS_SEQUENCES.length !== 0) {
SUCCESS_SEQUENCES.length = 0;
changed = true;
}
if(FAILED_SEQUENCES.length !== 0) {
FAILED_SEQUENCES.length = 0;
changed = true;
@@ -66,6 +86,9 @@ export const applyPacket = ({
bytes,
size
}) => {
let trustedSize = isSizeTrusted();
if(!isPacketInRange(sequence)) return;
const dataSize = PacketUtils.getPacketDataByteCount();
const offset = sequence * dataSize;
const length = offset + dataSize;
@@ -73,39 +96,179 @@ export const applyPacket = ({
if(FAILED_SEQUENCES.includes(sequence)) {
FAILED_SEQUENCES.splice(FAILED_SEQUENCES.indexOf(sequence), 1);
}
if(!SUCCESS_SEQUENCES.includes(sequence)) {
SUCCESS_SEQUENCES.push(sequence);
}
if(DATA.length < length) {
const copy = new Uint8ClampedArray(length);
copy.set(DATA.subarray(0, DATA.length), 0);
DATA = copy;
}
DATA.set(bytes, offset);
delete BITS[packetIndex];
if(!trustedSize && isSizeTrusted()) {
// We may now have a trusted size. update prior failures.
FAILED_SEQUENCES = FAILED_SEQUENCES.filter(isPacketInRange);
dispatcher.emit('sizeReceived');
}
dispatcher.emit('packetReceived');
} else {
console.log("Failed", sequence);
if(!FAILED_SEQUENCES.includes(sequence))
FAILED_SEQUENCES.push(sequence);
// do nothing if previously successful
if(!SUCCESS_SEQUENCES.includes(sequence)) {
// NOTE: Can we trust the sequence?
// Check if sequence out of range
if(!FAILED_SEQUENCES.includes(sequence))
FAILED_SEQUENCES.push(sequence);
dispatcher.emit('packetFailed', {sequence});
}
}
delete BITS[packetIndex]
}
export const getPercentReceived = () => {
if(SAMPLES_EXPECTED === 0) return 0;
return SAMPLES_RECEIVED / SAMPLES_EXPECTED;
export const getFailedPacketIndeces = () => FAILED_SEQUENCES;
export const countFailedPackets = () => FAILED_SEQUENCES.length;
export const countSuccessfulPackets = () => SUCCESS_SEQUENCES.length;
export const countExpectedPackets = () => {
if(!isSizeTrusted()) return 0;
return PacketUtils.packetStats(getSize()).packetCount;
}
export const setPacketsExpected = packetCount => {
if(packetCount < 0 || packetCount === Infinity) packetCount = 0;
// used when requesting individual packets out of sequence
SAMPLES_EXPECTED = packetCount * PacketUtils.getPacketSegmentCount();
}
export const getSizeAvailable = () => {
if(DATA_SIZE_BIT_COUNT === 0) return 1;
let lastBit = DATA_SIZE_BIT_COUNT;
let lastByte = Math.ceil(lastBit / 8);
if(DATA.length < lastByte) return false;
// Do we have a crc check on the size?
if(DATA_SIZE_CRC_BIT_COUNT !== 0) {
return getSizeCrcAvailable();
}
return true;
}
export const isSizeTrusted = () => {
if(!getSizeAvailable()) return false;
if(DATA_SIZE_CRC_BIT_COUNT !== 0) return getSizeCrcPassed();
return true;
}
export const getSize = () => {
if(DATA_SIZE_BIT_COUNT === 0) return 1;
if(!getSizeAvailable()) return -1;
let firstBit = 0;
let lastBit = DATA_SIZE_BIT_COUNT;
// Do we have the data?
let firstByte = Math.floor(firstBit / 8);
let lastByte = Math.ceil(lastBit / 8);
if(DATA.length < lastByte) return -1;
// Grab the data
let bits = bytesToBits(DATA.subarray(firstByte, lastByte));
if(firstBit % 8 !== 0) {
bits.splice(firstBit % 8);
}
bits.length = DATA_SIZE_BIT_COUNT
return bitsToInt(bits, DATA_SIZE_BIT_COUNT);
}
export const getSizeCrc = () => {
if(!getSizeCrcAvailable()) return CRC.INVALID;
let startBitIndex = DATA_SIZE_BIT_COUNT;
let endBitIndex = startBitIndex + DATA_SIZE_CRC_BIT_COUNT;
let startByte = Math.floor(startBitIndex / 8);
let endByte = Math.ceil(endBitIndex / 8);
if(DATA.length < endByte) return CRC.INVALID;
let bits = bytesToBits(DATA.subarray(startByte, endByte));
if(startBitIndex % 8 !== 0) bits.splice(0, startBitIndex);
bits.length = DATA_SIZE_CRC_BIT_COUNT;
return bitsToInt(bits, DATA_SIZE_CRC_BIT_COUNT);
}
export const getCrc = () => {
if(!getCrcAvailable()) return CRC.INVALID;
let startBitIndex = DATA_SIZE_BIT_COUNT + DATA_SIZE_CRC_BIT_COUNT;
let endBitIndex = startBitIndex + DATA_CRC_BIT_COUNT;
let startByte = Math.floor(startBitIndex / 8);
let endByte = Math.ceil(endBitIndex / 8);
if(DATA.length < endByte) return CRC.INVALID;
let bits = bytesToBits(DATA.subarray(startByte, endByte));
if(startBitIndex % 8 !== 0) bits.splice(0, startBitIndex);
bits.length = DATA_CRC_BIT_COUNT;
return bitsToInt(bits, DATA_CRC_BIT_COUNT);
}
export const getSizeCrcAvailable = () => {
if (DATA_SIZE_BIT_COUNT === 0) return false;
if (DATA_SIZE_CRC_BIT_COUNT === 0) return false;
const bitsNeeded = DATA_SIZE_BIT_COUNT + DATA_SIZE_CRC_BIT_COUNT;
return DATA.length >= Math.ceil(bitsNeeded / 8);
}
export const getCrcAvailable = () => {
if(DATA_CRC_BIT_COUNT === 0) return false;
if(!getSizeAvailable()) return false;
let byteCount = getSize();
if(DATA.length < byteCount) return false;
// Do we have enough bytes for the headers and underlying data?
let headerBitCount = DATA_SIZE_BIT_COUNT + DATA_CRC_BIT_COUNT + DATA_SIZE_CRC_BIT_COUNT;
if(headerBitCount % 8 !== 0)
headerBitCount += 8 - (headerBitCount % 8);
const headerByteCount = headerBitCount / 8;
byteCount += headerByteCount;
return DATA.length >= byteCount;
}
export const getSizeCrcPassed = () => {
if(!getSizeCrcAvailable()) return false;
const size = getSize();
const sizeCrc = getSizeCrc();
if(sizeCrc === CRC.INVALID) return false;
const crc = CRC.check(numberToBytes(size, DATA_SIZE_BIT_COUNT), DATA_SIZE_CRC_BIT_COUNT);
return crc === sizeCrc;
}
export const getCrcPassed = () => {
if(!getCrcAvailable()) return false;
if(!isSizeTrusted()) return false;
const size = getSize();
const crc = getCrc();
if(crc === CRC.INVALID) return false;
// Get Data
// How large is our header?
let headerBitCount = DATA_CRC_BIT_COUNT + DATA_SIZE_BIT_COUNT + DATA_SIZE_CRC_BIT_COUNT;
if(headerBitCount % 8 !== 0) headerBitCount += 8 - (headerBitCount % 8);
let headerByteCount = headerBitCount / 8;
// Get bytes needed to perform CRC check on
const data = DATA.subarray(headerByteCount, headerByteCount + size);
// Do the check
return crc === CRC.check(data, DATA_CRC_BIT_COUNT);
}
export const changeConfiguration = ({
segmentsPerPacket,
bitsPerPacket,
bitsPerSegment,
streamHeaders
streamHeaders,
dataCrcBitLength,
dataSizeBitCount,
dataSizeCrcBitCount
}) => {
BITS_PER_PACKET = bitsPerPacket;
SEGMENTS_PER_PACKET = segmentsPerPacket;
BITS_PER_SEGMENT = bitsPerSegment;
STREAM_HEADERS = streamHeaders;
DATA_CRC_BIT_COUNT = dataCrcBitLength;
DATA_SIZE_BIT_COUNT = dataSizeBitCount;
DATA_SIZE_CRC_BIT_COUNT = dataSizeCrcBitCount;
}
const noEncoding = bits => bits;
export const setPacketEncoding = ({ encode, decode } = {}) => {
@@ -118,6 +281,8 @@ export const addSample = (
bits
) => {
SAMPLES_RECEIVED++;
if(BITS[packetIndex] === undefined) {
BITS[packetIndex] = [];
}