show packet error stats
This commit is contained in:
187
StreamManager.js
187
StreamManager.js
@@ -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] = [];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user