Пример #1
0
        /// <summary>
        /// Sends a SSH_MSG_CHANNEL_DATA message with the specified payload.
        /// </summary>
        /// <param name="data">An array of <see cref="byte"/> containing the payload to send.</param>
        /// <param name="offset">The zero-based offset in <paramref name="data"/> at which to begin taking data from.</param>
        /// <param name="size">The number of bytes of <paramref name="data"/> to send.</param>
        /// <remarks>
        /// <para>
        /// When the size of the data to send exceeds the maximum packet size or the remote window
        /// size does not allow the full data to be sent, then this method will send the data in
        /// multiple chunks and will wait for the remote window size to be adjusted when it's zero.
        /// </para>
        /// <para>
        /// This is done to support SSH servers will a small window size that do not agressively
        /// increase their window size. We need to take into account that there may be SSH servers
        /// that only increase their window size when it has reached zero.
        /// </para>
        /// </remarks>
        public void SendData(byte[] data, int offset, int size)
        {
            // send channel messages only while channel is open
            if (!IsOpen)
            {
                return;
            }

            var totalBytesToSend = size;

            while (totalBytesToSend > 0)
            {
                var sizeOfCurrentMessage = GetDataLengthThatCanBeSentInMessage(totalBytesToSend);

                var channelDataMessage = new ChannelDataMessage(
                    RemoteChannelNumber,
                    data,
                    offset,
                    sizeOfCurrentMessage);
                _session.SendMessage(channelDataMessage);

                totalBytesToSend -= sizeOfCurrentMessage;
                offset           += sizeOfCurrentMessage;
            }
        }
Пример #2
0
        /// <summary>
        /// Sends channel data message to the servers.
        /// </summary>
        /// <param name="message">Channel data message.</param>
        /// <remarks>
        /// <para>
        /// When the data of the message exceeds the maximum packet size or the remote window
        /// size does not allow the full message to be sent, then this method will send the
        /// data in multiple chunks and will only wait for the remote window size to be adjusted
        /// when its zero.
        /// </para>
        /// <para>
        /// This is done to support SSH servers will a small window size that do not agressively
        /// increase their window size. We need to take into account that there may be SSH
        /// servers that only increase their window size when it has reached zero.
        /// </para>
        /// </remarks>
        protected void SendMessage(ChannelDataMessage message)
        {
            // send channel messages only while channel is open
            if (!IsOpen)
            {
                return;
            }

            var totalDataLength = message.Data.Length;
            var totalDataSent   = 0;

            var totalBytesToSend = totalDataLength;

            while (totalBytesToSend > 0)
            {
                var dataThatCanBeSentInMessage = GetDataLengthThatCanBeSentInMessage(totalBytesToSend);
                if (dataThatCanBeSentInMessage == totalDataLength)
                {
                    // we can send the message in one chunk
                    _session.SendMessage(message);
                }
                else
                {
                    // we need to send the message in multiple chunks
                    var dataToSend = new byte[dataThatCanBeSentInMessage];
                    Array.Copy(message.Data, totalDataSent, dataToSend, 0, dataThatCanBeSentInMessage);
                    _session.SendMessage(new ChannelDataMessage(message.LocalChannelNumber, dataToSend));
                }
                totalDataSent    += dataThatCanBeSentInMessage;
                totalBytesToSend -= dataThatCanBeSentInMessage;
            }
        }
Пример #3
0
        /// <summary>
        /// Sends channel data message to the servers.
        /// </summary>
        /// <remarks>This method takes care of managing the window size.</remarks>
        /// <param name="message">Channel data message.</param>
        protected void SendMessage(ChannelDataMessage message)
        {
            //  Send channel messages only while channel is open
            if (!this.IsOpen)
            {
                return;
            }

            var messageLength = message.Data.Length;

            do
            {
                lock (this._serverWindowSizeLock)
                {
                    var serverWindowSize = this.ServerWindowSize;
                    if (serverWindowSize < messageLength)
                    {
                        //  Wait for window to be big enough for this message
                        this._channelServerWindowAdjustWaitHandle.Reset();
                    }
                    else
                    {
                        this.ServerWindowSize -= (uint)messageLength;
                        break;
                    }
                }

                //  Wait for window to change
                this.WaitHandle(this._channelServerWindowAdjustWaitHandle);
            } while (true);

            this._session.SendMessage(message);
        }
Пример #4
0
        public void SendData(byte[] data)
        {
            Contract.Requires(data != null);

            var msg = new ChannelDataMessage();

            msg.RecipientChannel = ClientChannelId;

            var total  = (uint)data.Length;
            var offset = 0L;

            byte[] buf = null;
            do
            {
                var packetSize = Math.Min(Math.Min(ClientWindowSize, ClientMaxPacketSize), total);
                if (packetSize == 0)
                {
                    _sendingWindowWaitHandle.WaitOne();
                    continue;
                }

                if (buf == null || packetSize != buf.Length)
                {
                    buf = new byte[packetSize];
                }
                Array.Copy(data, offset, buf, 0, packetSize);

                msg.Data = buf;
                _connectionService._session.SendMessage(msg);

                ClientWindowSize -= packetSize;
                total            -= packetSize;
                offset           += packetSize;
            } while (total > 0);
        }
        public void GetBytes()
        {
            var random = new Random();

            var localChannelNumber = (uint)random.Next(0, int.MaxValue);
            var data   = CryptoAbstraction.GenerateRandom(random.Next(10, 20));
            var offset = random.Next(0, data.Length - 1);
            var size   = random.Next(0, data.Length - offset);

            var target = new ChannelDataMessage(localChannelNumber, data, offset, size);

            var bytes = target.GetBytes();

            var expectedBytesLength = 1; // Type

            expectedBytesLength += 4;    // LocalChannelNumber
            expectedBytesLength += 4;    // Data length
            expectedBytesLength += size; // Data

            Assert.AreEqual(expectedBytesLength, bytes.Length);

            var sshDataStream = new SshDataStream(bytes);

            Assert.AreEqual(ChannelDataMessage.MessageNumber, sshDataStream.ReadByte());
            Assert.AreEqual(localChannelNumber, sshDataStream.ReadUInt32());
            Assert.AreEqual((uint)size, sshDataStream.ReadUInt32());

            var actualData = new byte[size];

            sshDataStream.Read(actualData, 0, size);
            Assert.IsTrue(actualData.SequenceEqual(data.Take(offset, size)));

            Assert.IsTrue(sshDataStream.IsEndOfData);
        }
Пример #6
0
        public void Load()
        {
            var random = new Random();

            var localChannelNumber = (uint)random.Next(0, int.MaxValue);
            var data = new byte[random.Next(10, 20)];

            random.NextBytes(data);
#if TUNING
            var offset             = random.Next(2, 4);
            var size               = random.Next(5, 9);
            var channelDataMessage = new ChannelDataMessage(localChannelNumber, data, offset, size);
#else
            var offset             = 0;
            var size               = data.Length;
            var channelDataMessage = new ChannelDataMessage(localChannelNumber, data);
#endif
            var bytes  = channelDataMessage.GetBytes();
            var target = new ChannelDataMessage();

            target.Load(bytes);

            Assert.IsTrue(target.Data.SequenceEqual(data.Take(offset, size)));
#if TUNING
            Assert.AreEqual(0, target.Offset);
            Assert.AreEqual(size, target.Size);
#endif
        }
        public void DefaultConstructor()
        {
            var target = new ChannelDataMessage();

            Assert.IsNull(target.Data);
            Assert.AreEqual(0, target.Offset);
            Assert.AreEqual(0, target.Size);
        }
Пример #8
0
        public void ChannelDataMessageConstructorTest1()
        {
            uint localChannelNumber = 0;      // TODO: Initialize to an appropriate value

            byte[]             data   = null; // TODO: Initialize to an appropriate value
            ChannelDataMessage target = new ChannelDataMessage(localChannelNumber, data);

            Assert.Inconclusive("TODO: Implement code to verify target");
        }
        public void Constructor_LocalChannelNumberAndDataAndOffsetAndSize()
        {
            var       localChannelNumber = (uint)new Random().Next(0, int.MaxValue);
            var       data   = new byte[4];
            const int offset = 2;
            const int size   = 1;

            var target = new ChannelDataMessage(localChannelNumber, data, offset, size);

            Assert.AreSame(data, target.Data);
            Assert.AreEqual(offset, target.Offset);
            Assert.AreEqual(size, target.Size);
        }
Пример #10
0
        public void Constructor_LocalChannelNumberAndData()
        {
            var random = new Random();

            var localChannelNumber = (uint)random.Next(0, int.MaxValue);
            var data = new byte[3];

            var target = new ChannelDataMessage(localChannelNumber, data);

            Assert.AreSame(data, target.Data);
            Assert.AreEqual(0, target.Offset);
            Assert.AreEqual(data.Length, target.Size);
        }
Пример #11
0
        /// <summary>
        /// Sends channel data message to the servers.
        /// </summary>
        /// <remarks>This method takes care of managing the window size.</remarks>
        /// <param name="message">Channel data message.</param>
        protected void SendMessage(ChannelDataMessage message)
        {
            //  Send channel messages only while channel is open
            if (!this.IsOpen)
            {
                return;
            }

            if (this.ServerWindowSize < 1)
            {
                //  Wait for window to be adjust
                this._session.WaitHandle(this._channelWindowAdjustWaitHandle);
            }

            this.ServerWindowSize -= (uint)message.Data.Length;
            this._session.SendMessage(message);
        }
        public void Load()
        {
            var random = new Random();

            var localChannelNumber = (uint)random.Next(0, int.MaxValue);
            var data = CryptoAbstraction.GenerateRandom(random.Next(10, 20));

            var offset             = random.Next(0, data.Length - 1);
            var size               = random.Next(0, data.Length - offset);
            var channelDataMessage = new ChannelDataMessage(localChannelNumber, data, offset, size);
            var bytes              = channelDataMessage.GetBytes();
            var target             = new ChannelDataMessage();

            target.Load(bytes, 1, bytes.Length - 1); // skip message type

            Assert.IsTrue(target.Data.SequenceEqual(data.Take(offset, size)));
            Assert.AreEqual(0, target.Offset);
            Assert.AreEqual(size, target.Size);
        }
        //public void SendData(byte[] data)
        //{
        //    this._session.SendMessage(new ChannelDataMessage(this._channel.RemoteChannelNumber, data));
        //}

        public void SendData(ChannelDataMessage message)
        {
            this._session.SendMessage(message);
        }
Пример #14
0
        private void HandleMessage(ChannelDataMessage message)
        {
            var service = this.GetService <ConnectionService>();

            service?.HandleMessageCore(message);
        }
Пример #15
0
        private void HandleMessage(ChannelDataMessage message)
        {
            var channel = FindChannelByServerId <Channel>(message.RecipientChannel);

            channel.OnData(message.Data);
        }
Пример #16
0
        public void ChannelDataMessageConstructorTest()
        {
            ChannelDataMessage target = new ChannelDataMessage();

            Assert.Inconclusive("TODO: Implement code to verify target");
        }