using System;
using System.Globalization;
using System.IO;
using System.Text;
namespace Renci.SshNet.Common
{
public class SshDataStream : MemoryStream
{
public SshDataStream(int capacity)
: base(capacity)
{
}
public SshDataStream(byte[] buffer)
: base(buffer)
{
}
///
/// Gets a value indicating whether all data from the SSH data stream has been read.
///
///
/// true if this instance is end of data; otherwise, false.
///
public bool IsEndOfData
{
get
{
return Position >= Length;
}
}
///
/// Writes an to the SSH data stream.
///
/// data to write.
public void Write(uint value)
{
var bytes = value.GetBytes();
Write(bytes, 0, bytes.Length);
}
///
/// Writes an to the SSH data stream.
///
/// data to write.
public void Write(ulong value)
{
var bytes = value.GetBytes();
Write(bytes, 0, bytes.Length);
}
///
/// Writes a into the SSH data stream.
///
/// The to write.
public void Write(BigInteger data)
{
var bytes = data.ToByteArray().Reverse();
WriteBinary(bytes, 0, bytes.Length);
}
///
/// Writes bytes array data into the SSH data stream.
///
/// Byte array data to write.
/// is null.
public void Write(byte[] data)
{
if (data == null)
throw new ArgumentNullException("data");
Write(data, 0, data.Length);
}
///
/// Reads a byte array from the SSH data stream.
///
///
/// The byte array read from the SSH data stream.
///
public byte[] ReadBinary()
{
var length = ReadUInt32();
if (length > int.MaxValue)
{
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Data longer than {0} is not supported.", int.MaxValue));
}
return ReadBytes((int)length);
}
///
/// Writes a buffer preceded by its length into the SSH data stream.
///
/// The data to write.
/// is null.
public void WriteBinary(byte[] buffer)
{
if (buffer == null)
throw new ArgumentNullException("buffer");
WriteBinary(buffer, 0, buffer.Length);
}
///
/// Writes a buffer preceded by its length into the SSH data stream.
///
/// An array of bytes. This method write bytes from buffer to the current SSH data stream.
/// The zero-based byte offset in at which to begin writing bytes to the SSH data stream.
/// The number of bytes to be written to the current SSH data stream.
/// is null.
/// The sum of and is greater than the buffer length.
/// or is negative.
public void WriteBinary(byte[] buffer, int offset, int count)
{
Write((uint) count);
Write(buffer, offset, count);
}
///
/// Writes string data to the SSH data stream using the specified encoding.
///
/// The string data to write.
/// The character encoding to use.
/// is null.
/// is null.
public void Write(string s, Encoding encoding)
{
if (encoding == null)
throw new ArgumentNullException("encoding");
var bytes = encoding.GetBytes(s);
WriteBinary(bytes, 0, bytes.Length);
}
///
/// Reads a from the SSH datastream.
///
///
/// The read from the SSH data stream.
///
public BigInteger ReadBigInt()
{
var length = ReadUInt32();
var data = ReadBytes((int) length);
return new BigInteger(data.Reverse());
}
///
/// Reads the next data type from the SSH data stream.
///
///
/// The read from the SSH data stream.
///
public uint ReadUInt32()
{
var data = ReadBytes(4);
return (uint) (data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]);
}
///
/// Reads the next data type from the SSH data stream.
///
///
/// The read from the SSH data stream.
///
public ulong ReadUInt64()
{
var data = ReadBytes(8);
return ((ulong) data[0] << 56 | (ulong) data[1] << 48 | (ulong) data[2] << 40 | (ulong) data[3] << 32 |
(ulong) data[4] << 24 | (ulong) data[5] << 16 | (ulong) data[6] << 8 | data[7]);
}
///
/// Reads the next data type from the SSH data stream.
///
///
/// The read from the SSH data stream.
///
public string ReadString(Encoding encoding)
{
var length = ReadUInt32();
if (length > int.MaxValue)
{
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Strings longer than {0} is not supported.", int.MaxValue));
}
var bytes = ReadBytes((int) length);
return encoding.GetString(bytes, 0, bytes.Length);
}
///
/// Reads next specified number of bytes data type from internal buffer.
///
/// Number of bytes to read.
/// An array of bytes that was read from the internal buffer.
/// is greater than the internal buffer size.
private byte[] ReadBytes(int length)
{
var data = new byte[length];
var bytesRead = Read(data, 0, length);
if (bytesRead < length)
throw new ArgumentOutOfRangeException("length");
return data;
}
///
/// Writes the stream contents to a byte array, regardless of the .
///
///
/// This method returns the contents of the as a byte array.
///
///
/// If the current instance was constructed on a provided byte array, a copy of the section of the array
/// to which this instance has access is returned.
///
public override byte[] ToArray()
{
if (Capacity == Length)
{
#if FEATURE_MEMORYSTREAM_GETBUFFER
return GetBuffer();
#elif FEATURE_MEMORYSTREAM_TRYGETBUFFER
ArraySegment buffer;
if (TryGetBuffer(out buffer))
return buffer.Array;
#endif
}
return base.ToArray();
}
}
}