/// <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; } }
/// <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; } }
/// <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); }
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); }
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); }
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); }
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); }
/// <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); }
private void HandleMessage(ChannelDataMessage message) { var service = this.GetService <ConnectionService>(); service?.HandleMessageCore(message); }
private void HandleMessage(ChannelDataMessage message) { var channel = FindChannelByServerId <Channel>(message.RecipientChannel); channel.OnData(message.Data); }
public void ChannelDataMessageConstructorTest() { ChannelDataMessage target = new ChannelDataMessage(); Assert.Inconclusive("TODO: Implement code to verify target"); }