handleRead method
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;
}
}