readFrame method
Frame?
readFrame({})
inherited
Not part of public API
Implementation
Frame? readFrame({
RiftCipher? cipher,
int? keyCrc,
bool lazy = false,
int frameOffset = 0,
bool verbatim = false,
}) {
// frame length is stored on 4 bytes
if (availableBytes < 4) return null;
// frame length should be at least 8 bytes
final frameLength = readUint32();
if (frameLength < 8) return null;
// frame is bigger than avaible bytes
if (availableBytes < frameLength - 4) return null;
final crc = _buffer.readUint32(_offset + frameLength - 8);
final crcOffset = _offset - 4;
final crcLength = frameLength - 4;
final computedCrc = Crc32.compute(
_buffer,
offset: crcOffset,
length: crcLength,
crc: keyCrc ?? cipher?.calculateKeyCrc() ?? 0,
);
// frame is corrupted or provided chiper is different
if (computedCrc != crc) {
if (keyCrc != null) {
// Attempt to compute the crc without the key crc
// This maintains compatibility with data written by IsolatedRift before keyCrc was introduced
final computedCrc2 = Crc32.compute(
_buffer,
offset: crcOffset,
length: crcLength,
);
if (computedCrc2 != crc) return null;
if (Logger.crcRecomputeWarning && !_crcRecomputeWarningPrinted) {
Logger.w(RiftWarning.crcRecomputeNeeded);
_crcRecomputeWarningPrinted = true;
}
} else {
return null;
}
}
_limitAvailableBytes(frameLength - 8);
Frame frame;
final dynamic key = readKey();
if (availableBytes == 0) {
frame = Frame.deleted(key);
} else if (lazy) {
frame = Frame.lazy(key);
} else if (verbatim) {
frame = Frame(key, viewBytes(availableBytes));
} else if (cipher == null) {
frame = Frame(key, read());
} else {
frame = Frame(key, readEncrypted(cipher));
}
frame
..length = frameLength
..offset = frameOffset;
skip(availableBytes);
_resetLimit();
skip(4); // Skip CRC
return frame;
}