/// <summary> /// Writes the current message to the specified <see cref="SshDataStream"/>. /// </summary> /// <param name="stream">The <see cref="SshDataStream"/> to write the message to.</param> protected override void WriteBytes(SshDataStream stream) { const int sizeOfDataLengthBytes = 4; var startPosition = stream.Position; // skip 4 bytes for the length of the SFTP message data stream.Seek(sizeOfDataLengthBytes, SeekOrigin.Current); // write the SFTP message data to the stream base.WriteBytes(stream); // save where we were positioned when we finished writing the SSH message data var endPosition = stream.Position; // determine the length of the SSH message data var dataLength = endPosition - startPosition - sizeOfDataLengthBytes; // write the length of the SFTP message where we were positioned before we started // writing the SFTP message data stream.Position = startPosition; stream.Write((uint)dataLength); // move back to we were positioned when we finished writing the SFTP message data stream.Position = endPosition; }
internal byte[] GetPacket(byte paddingMultiplier, Compressor compressor) { const int outboundPacketSequenceSize = 4; var messageLength = BufferCapacity; SshDataStream sshDataStream; if (messageLength == -1 || compressor != null) { sshDataStream = new SshDataStream(DefaultCapacity); // skip: // * 4 bytes for the outbound packet sequence // * 4 bytes for the packet data length // * one byte for the packet padding length sshDataStream.Seek(outboundPacketSequenceSize + 4 + 1, SeekOrigin.Begin); if (compressor != null) { // obtain uncompressed message payload var uncompressedDataStream = new SshDataStream(messageLength != -1 ? messageLength : DefaultCapacity); WriteBytes(uncompressedDataStream); // compress message payload var compressedMessageData = compressor.Compress(uncompressedDataStream.ToArray()); // add compressed message payload sshDataStream.Write(compressedMessageData, 0, compressedMessageData.Length); } else { // add message payload WriteBytes(sshDataStream); } messageLength = (int)sshDataStream.Length - (outboundPacketSequenceSize + 4 + 1); var packetLength = messageLength + 4 + 1; // determine the padding length var paddingLength = GetPaddingLength(paddingMultiplier, packetLength); // add padding bytes var paddingBytes = new byte[paddingLength]; HashAlgorithmFactory.GenerateRandom(paddingBytes); sshDataStream.Write(paddingBytes, 0, paddingLength); var packetDataLength = GetPacketDataLength(messageLength, paddingLength); // skip bytes for outbound packet sequence sshDataStream.Seek(outboundPacketSequenceSize, SeekOrigin.Begin); // add packet data length sshDataStream.Write(packetDataLength.GetBytes(), 0, 4); // add packet padding length sshDataStream.WriteByte(paddingLength); } else { var packetLength = messageLength + 4 + 1; // determine the padding length var paddingLength = GetPaddingLength(paddingMultiplier, packetLength); var packetDataLength = GetPacketDataLength(messageLength, paddingLength); // lets construct an SSH data stream of the exact size required sshDataStream = new SshDataStream(packetLength + paddingLength + outboundPacketSequenceSize); // skip bytes for outbound packet sequenceSize sshDataStream.Seek(outboundPacketSequenceSize, SeekOrigin.Begin); // add packet data length sshDataStream.Write(packetDataLength.GetBytes(), 0, 4); // add packet padding length sshDataStream.WriteByte(paddingLength); // add message payload WriteBytes(sshDataStream); // add padding bytes var paddingBytes = new byte[paddingLength]; HashAlgorithmFactory.GenerateRandom(paddingBytes); sshDataStream.Write(paddingBytes, 0, paddingLength); } return(sshDataStream.ToArray()); }