readFrame method

Frame? readFrame({
  1. RiftCipher? cipher,
  2. int? keyCrc,
  3. bool lazy = false,
  4. int frameOffset = 0,
  5. bool verbatim = false,
})
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;
}