handleRead method

void handleRead(
  1. Uint8List dataChunk
)

Callback supplied to socket.listen.

Implementation

void handleRead(Uint8List dataChunk) {
  readBuffer.add(dataChunk);

  /// Initialze with an ASCII version exchange.
  if (state == SSHTransportState.INIT) {
    handleInitialState();
    if (state == SSHTransportState.INIT) return;
  }

  /// Thereafter we speak RFC4253 Binary Packet Protocol.
  while (true) {
    bool encrypted = state > SSHTransportState.FIRST_NEWKEYS;

    /// We only need to decrypt one cipher block to determine the next packet length.
    if (packetLen == 0) {
      packetMacLen = macHashLenS != 0
          ? (macPrefixS2c != 0 ? macPrefixS2c : macHashLenS)
          : 0;
      if (readBuffer.data.length < BinaryPacket.headerSize ||
          (encrypted && readBuffer.data.length < decryptBlockSize)) {
        return;
      }
      if (encrypted) {
        decryptBuf =
            readCipher(viewUint8List(readBuffer.data, 0, decryptBlockSize));
      }
      BinaryPacket binaryPacket =
          BinaryPacket(encrypted ? decryptBuf : readBuffer.data);
      packetLen = 4 + binaryPacket.length + packetMacLen;
      padding = binaryPacket.padding;
    }

    /// Wait until we've read the entire packet.
    if (readBuffer.data.length < packetLen) return;

    /// Decrypts the remaining cipher blocks in the packet.
    if (encrypted) {
      decryptBuf = appendUint8List(
          decryptBuf,
          readCipher(viewUint8List(readBuffer.data, decryptBlockSize,
              packetLen - decryptBlockSize - packetMacLen)));
    }

    /// Verifies the Message Authentication Code (MAC).
    sequenceNumberS2c++;
    if (encrypted && packetMacLen != 0) {
      Uint8List mac = computeMAC(
          MAC.mac(macIdS2c),
          macHashLenS,
          viewUint8List(decryptBuf, 0, packetLen - packetMacLen),
          sequenceNumberS2c - 1,
          integrityS2c,
          macPrefixS2c);
      if (!equalUint8List(
          mac,
          viewUint8List(
              readBuffer.data, packetLen - packetMacLen, packetMacLen))) {
        throw FormatException('$hostport: verify MAC failed');
      }
    }

    /// Handles the packet.
    Uint8List packet = encrypted ? decryptBuf : readBuffer.data;
    packetS = SerializableInput(viewUint8List(packet, BinaryPacket.headerSize,
        packetLen - BinaryPacket.headerSize - packetMacLen - padding));
    if (zreader != null) {
      /// If compression has been negotiated, the 'payload' field (and only it)
      /// will be compressed using the negotiated algorithm.
      /// https://tools.ietf.org/html/rfc4253#section-6.2
      packetS = SerializableInput(zreader.convert(packetS.buffer));
    }
    handlePacket(packet);
    readBuffer.flush(packetLen);
    packetLen = 0;
  }
}