< Summary

Information
Class: Renci.SshNet.Messages.Message
Assembly: Renci.SshNet
File(s): \home\appveyor\projects\ssh-net\src\Renci.SshNet\Messages\Message.cs
Line coverage
85%
Covered lines: 69
Uncovered lines: 12
Coverable lines: 81
Total lines: 191
Line coverage: 85.1%
Branch coverage
64%
Covered branches: 9
Total branches: 14
Branch coverage: 64.2%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
get_BufferCapacity()100%1100%
WriteBytes(...)50%285.71%
GetPacket(...)62.5%882.22%
GetPacketDataLength(...)100%1100%
GetPaddingLength(...)100%2100%
ToString()50%275%

File(s)

\home\appveyor\projects\ssh-net\src\Renci.SshNet\Messages\Message.cs

#LineLine coverage
 1using System.Globalization;
 2using System.IO;
 3
 4using Renci.SshNet.Abstractions;
 5using Renci.SshNet.Common;
 6using Renci.SshNet.Compression;
 7
 8namespace Renci.SshNet.Messages
 9{
 10    /// <summary>
 11    /// Base class for all SSH protocol messages.
 12    /// </summary>
 13    public abstract class Message : SshData
 14    {
 15        /// <summary>
 16        /// Gets the size of the message in bytes.
 17        /// </summary>
 18        /// <value>
 19        /// The size of the messages in bytes.
 20        /// </value>
 21        protected override int BufferCapacity
 22        {
 23            get
 5272024            {
 5272025                return 1; // Message type
 5272026            }
 27        }
 28
 29        /// <summary>
 30        /// Writes the message to the specified <see cref="SshDataStream"/>.
 31        /// </summary>
 32        /// <param name="stream">The <see cref="SshDataStream"/> to write the message to.</param>
 33        protected override void WriteBytes(SshDataStream stream)
 5694434        {
 5694435            var enumerator = GetType().GetCustomAttributes<MessageAttribute>(inherit: true).GetEnumerator();
 36            try
 5694437            {
 5694438                if (!enumerator.MoveNext())
 039                {
 040                    throw new SshException(string.Format(CultureInfo.CurrentCulture, "Type '{0}' is not a valid message 
 41                }
 42
 5694443                var messageAttribute = enumerator.Current;
 5694444                stream.WriteByte(messageAttribute.Number);
 5694445                base.WriteBytes(stream);
 5694446            }
 47            finally
 5694448            {
 5694449                enumerator.Dispose();
 5694450            }
 5694451        }
 52
 53        internal byte[] GetPacket(byte paddingMultiplier, Compressor compressor)
 5451054        {
 55            const int outboundPacketSequenceSize = 4;
 56
 5451057            var messageLength = BufferCapacity;
 58
 5451059            if (messageLength == -1 || compressor != null)
 182360            {
 182361                using (var sshDataStream = new SshDataStream(DefaultCapacity))
 182362                {
 63                    // skip:
 64                    // * 4 bytes for the outbound packet sequence
 65                    // * 4 bytes for the packet data length
 66                    // * one byte for the packet padding length
 182367                    _ = sshDataStream.Seek(outboundPacketSequenceSize + 4 + 1, SeekOrigin.Begin);
 68
 182369                    if (compressor != null)
 070                    {
 71                        // obtain uncompressed message payload
 072                        using (var uncompressedDataStream = new SshDataStream(messageLength != -1 ? messageLength : Defa
 073                        {
 074                            WriteBytes(uncompressedDataStream);
 75
 76                            // compress message payload
 077                            var compressedMessageData = compressor.Compress(uncompressedDataStream.ToArray());
 78
 79                            // add compressed message payload
 080                            sshDataStream.Write(compressedMessageData, 0, compressedMessageData.Length);
 081                        }
 082                    }
 83                    else
 182384                    {
 85                        // add message payload
 182386                        WriteBytes(sshDataStream);
 182387                    }
 88
 182389                    messageLength = (int) sshDataStream.Length - (outboundPacketSequenceSize + 4 + 1);
 90
 182391                    var packetLength = messageLength + 4 + 1;
 92
 93                    // determine the padding length
 182394                    var paddingLength = GetPaddingLength(paddingMultiplier, packetLength);
 95
 96                    // add padding bytes
 182397                    var paddingBytes = new byte[paddingLength];
 182398                    CryptoAbstraction.GenerateRandom(paddingBytes);
 182399                    sshDataStream.Write(paddingBytes, 0, paddingLength);
 100
 1823101                    var packetDataLength = GetPacketDataLength(messageLength, paddingLength);
 102
 103                    // skip bytes for outbound packet sequence
 1823104                    _ = sshDataStream.Seek(outboundPacketSequenceSize, SeekOrigin.Begin);
 105
 106                    // add packet data length
 1823107                    sshDataStream.Write(packetDataLength);
 108
 109                    // add packet padding length
 1823110                    sshDataStream.WriteByte(paddingLength);
 111
 1823112                    return sshDataStream.ToArray();
 113                }
 114            }
 115            else
 52687116            {
 52687117                var packetLength = messageLength + 4 + 1;
 118
 119                // determine the padding length
 52687120                var paddingLength = GetPaddingLength(paddingMultiplier, packetLength);
 121
 52687122                var packetDataLength = GetPacketDataLength(messageLength, paddingLength);
 123
 124                // lets construct an SSH data stream of the exact size required
 52687125                using (var sshDataStream = new SshDataStream(packetLength + paddingLength + outboundPacketSequenceSize))
 52687126                {
 127                    // skip bytes for outbound packet sequenceSize
 52687128                    _ = sshDataStream.Seek(outboundPacketSequenceSize, SeekOrigin.Begin);
 129
 130                    // add packet data length
 52687131                    sshDataStream.Write(packetDataLength);
 132
 133                    // add packet padding length
 52687134                    sshDataStream.WriteByte(paddingLength);
 135
 136                    // add message payload
 52687137                    WriteBytes(sshDataStream);
 138
 139                    // add padding bytes
 52687140                    var paddingBytes = new byte[paddingLength];
 52687141                    CryptoAbstraction.GenerateRandom(paddingBytes);
 52687142                    sshDataStream.Write(paddingBytes, 0, paddingLength);
 143
 52687144                    return sshDataStream.ToArray();
 145                }
 146            }
 54510147        }
 148
 149        private static uint GetPacketDataLength(int messageLength, byte paddingLength)
 54510150        {
 54510151            return (uint) (messageLength + paddingLength + 1);
 54510152        }
 153
 154        private static byte GetPaddingLength(byte paddingMultiplier, long packetLength)
 54510155        {
 54510156            var paddingLength = (byte)((-packetLength) & (paddingMultiplier - 1));
 157
 54510158            if (paddingLength < paddingMultiplier)
 54510159            {
 54510160                paddingLength += paddingMultiplier;
 54510161            }
 162
 54510163            return paddingLength;
 54510164        }
 165
 166        /// <summary>
 167        /// Returns a <see cref="string"/> that represents this instance.
 168        /// </summary>
 169        /// <returns>
 170        /// A <see cref="string"/> that represents this instance.
 171        /// </returns>
 172        public override string ToString()
 106374173        {
 106374174            using (var enumerator = GetType().GetCustomAttributes<MessageAttribute>(inherit: true).GetEnumerator())
 106374175            {
 106374176                if (!enumerator.MoveNext())
 0177                {
 0178                    return string.Format(CultureInfo.CurrentCulture, "'{0}' without Message attribute.", GetType().FullN
 179                }
 180
 106374181                return enumerator.Current.Name;
 182            }
 106374183        }
 184
 185        /// <summary>
 186        /// Process the current message for the specified <see cref="Session"/>.
 187        /// </summary>
 188        /// <param name="session">The <see cref="Session"/> for which to process the current message.</param>
 189        internal abstract void Process(Session session);
 190    }
 191}