Ref System.Memory for net462 and netstandard2.0 (#1417)

* Ref System.Memory for net462 and netstandard2.0.
Use System.Buffers.Binary.BinaryPrimitives instead of Renci.SshNet.Common.Pack

* Remove unnecessary `AsSpan()`

* Apply suggestions from code review

* that's what I get for being lazy

---------

Co-authored-by: Rob Hague <rob.hague00@gmail.com>
Co-authored-by: Robert Hague <rh@johnstreetcapital.com>
This commit is contained in:
Scott Xu
2024-07-04 19:14:09 +08:00
committed by GitHub
parent 8e8829ef96
commit c552d0d60b
12 changed files with 64 additions and 530 deletions
+3 -1
View File
@@ -1,4 +1,5 @@
using System;
using System.Buffers.Binary;
using System.Collections.Generic;
namespace Renci.SshNet.Common
@@ -198,7 +199,8 @@ namespace Renci.SshNet.Common
/// <param name="data">UInt32 data to write.</param>
public void Write(uint data)
{
var bytes = Pack.UInt32ToBigEndian(data);
var bytes = new byte[sizeof(uint)];
BinaryPrimitives.WriteUInt32BigEndian(bytes, data);
_data.Add(Integer);
var length = GetLength(bytes.Length);
WriteBytes(length);
-282
View File
@@ -1,282 +0,0 @@
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
using System;
using System.Buffers.Binary;
#endif
namespace Renci.SshNet.Common
{
/// <summary>
/// Provides convenience methods for conversion to and from both Big Endian and Little Endian.
/// </summary>
internal static class Pack
{
/// <summary>
/// Converts little endian bytes into number.
/// </summary>
/// <param name="buffer">The buffer.</param>
/// <returns>Converted <see cref="ushort" />.</returns>
internal static ushort LittleEndianToUInt16(byte[] buffer)
{
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
return BinaryPrimitives.ReadUInt16LittleEndian(buffer);
#else
ushort n = buffer[0];
n |= (ushort)(buffer[1] << 8);
return n;
#endif
}
/// <summary>
/// Converts little endian bytes into number.
/// </summary>
/// <param name="buffer">The buffer.</param>
/// <returns>Converted <see cref="uint" />.</returns>
internal static uint LittleEndianToUInt32(byte[] buffer)
{
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
return BinaryPrimitives.ReadUInt32LittleEndian(buffer);
#else
uint n = buffer[0];
n |= (uint)buffer[1] << 8;
n |= (uint)buffer[2] << 16;
n |= (uint)buffer[3] << 24;
return n;
#endif
}
/// <summary>
/// Converts little endian bytes into number.
/// </summary>
/// <param name="buffer">The buffer.</param>
/// <returns>Converted <see cref="ulong" />.</returns>
internal static ulong LittleEndianToUInt64(byte[] buffer)
{
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
return BinaryPrimitives.ReadUInt64LittleEndian(buffer);
#else
ulong n = buffer[0];
n |= (ulong)buffer[1] << 8;
n |= (ulong)buffer[2] << 16;
n |= (ulong)buffer[3] << 24;
n |= (ulong)buffer[4] << 32;
n |= (ulong)buffer[5] << 40;
n |= (ulong)buffer[6] << 48;
n |= (ulong)buffer[7] << 56;
return n;
#endif
}
/// <summary>
/// Populates buffer with little endian number representation.
/// </summary>
/// <param name="value">The number to convert.</param>
internal static byte[] UInt16ToLittleEndian(ushort value)
{
var buffer = new byte[2];
UInt16ToLittleEndian(value, buffer);
return buffer;
}
/// <summary>
/// Populates buffer with little endian number representation.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <param name="buffer">The buffer.</param>
private static void UInt16ToLittleEndian(ushort value, byte[] buffer)
{
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
BinaryPrimitives.WriteUInt16LittleEndian(buffer, value);
#else
buffer[0] = (byte)(value & 0x00FF);
buffer[1] = (byte)((value & 0xFF00) >> 8);
#endif
}
/// <summary>
/// Populates buffer with little endian number representation.
/// </summary>
/// <param name="value">The number to convert.</param>
internal static byte[] UInt32ToLittleEndian(uint value)
{
var buffer = new byte[4];
UInt32ToLittleEndian(value, buffer);
return buffer;
}
/// <summary>
/// Populates buffer with little endian number representation.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <param name="buffer">The buffer.</param>
private static void UInt32ToLittleEndian(uint value, byte[] buffer)
{
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
BinaryPrimitives.WriteUInt32LittleEndian(buffer, value);
#else
buffer[0] = (byte)(value & 0x000000FF);
buffer[1] = (byte)((value & 0x0000FF00) >> 8);
buffer[2] = (byte)((value & 0x00FF0000) >> 16);
buffer[3] = (byte)((value & 0xFF000000) >> 24);
#endif
}
/// <summary>
/// Populates buffer with little endian number representation.
/// </summary>
/// <param name="value">The number to convert.</param>
internal static byte[] UInt64ToLittleEndian(ulong value)
{
var buffer = new byte[8];
UInt64ToLittleEndian(value, buffer);
return buffer;
}
/// <summary>
/// Populates buffer with little endian number representation.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <param name="buffer">The buffer.</param>
private static void UInt64ToLittleEndian(ulong value, byte[] buffer)
{
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
BinaryPrimitives.WriteUInt64LittleEndian(buffer, value);
#else
buffer[0] = (byte)(value & 0x00000000000000FF);
buffer[1] = (byte)((value & 0x000000000000FF00) >> 8);
buffer[2] = (byte)((value & 0x0000000000FF0000) >> 16);
buffer[3] = (byte)((value & 0x00000000FF000000) >> 24);
buffer[4] = (byte)((value & 0x000000FF00000000) >> 32);
buffer[5] = (byte)((value & 0x0000FF0000000000) >> 40);
buffer[6] = (byte)((value & 0x00FF000000000000) >> 48);
buffer[7] = (byte)((value & 0xFF00000000000000) >> 56);
#endif
}
internal static byte[] UInt16ToBigEndian(ushort value)
{
var buffer = new byte[2];
UInt16ToBigEndian(value, buffer, offset: 0);
return buffer;
}
internal static void UInt16ToBigEndian(ushort value, byte[] buffer, int offset)
{
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
BinaryPrimitives.WriteUInt16BigEndian(buffer.AsSpan(offset), value);
#else
buffer[offset] = (byte)(value >> 8);
buffer[offset + 1] = (byte)(value & 0x00FF);
#endif
}
internal static void UInt32ToBigEndian(uint value, byte[] buffer)
{
UInt32ToBigEndian(value, buffer, offset: 0);
}
internal static void UInt32ToBigEndian(uint value, byte[] buffer, int offset)
{
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
BinaryPrimitives.WriteUInt32BigEndian(buffer.AsSpan(offset), value);
#else
buffer[offset++] = (byte)((value & 0xFF000000) >> 24);
buffer[offset++] = (byte)((value & 0x00FF0000) >> 16);
buffer[offset++] = (byte)((value & 0x0000FF00) >> 8);
buffer[offset] = (byte)(value & 0x000000FF);
#endif
}
internal static byte[] UInt32ToBigEndian(uint value)
{
var buffer = new byte[4];
UInt32ToBigEndian(value, buffer);
return buffer;
}
internal static byte[] UInt64ToBigEndian(ulong value)
{
var buffer = new byte[8];
UInt64ToBigEndian(value, buffer, offset: 0);
return buffer;
}
private static void UInt64ToBigEndian(ulong value, byte[] buffer, int offset)
{
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
BinaryPrimitives.WriteUInt64BigEndian(buffer.AsSpan(offset), value);
#else
buffer[offset++] = (byte)((value & 0xFF00000000000000) >> 56);
buffer[offset++] = (byte)((value & 0x00FF000000000000) >> 48);
buffer[offset++] = (byte)((value & 0x0000FF0000000000) >> 40);
buffer[offset++] = (byte)((value & 0x000000FF00000000) >> 32);
buffer[offset++] = (byte)((value & 0x00000000FF000000) >> 24);
buffer[offset++] = (byte)((value & 0x0000000000FF0000) >> 16);
buffer[offset++] = (byte)((value & 0x000000000000FF00) >> 8);
buffer[offset] = (byte)(value & 0x00000000000000FF);
#endif
}
/// <summary>
/// Converts big endian bytes into number.
/// </summary>
/// <param name="buffer">The buffer.</param>
/// <returns>Converted <see cref="ushort" />.</returns>
internal static ushort BigEndianToUInt16(byte[] buffer)
{
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
return BinaryPrimitives.ReadUInt16BigEndian(buffer);
#else
return (ushort)(buffer[0] << 8 | buffer[1]);
#endif
}
/// <summary>
/// Converts big endian bytes into number.
/// </summary>
/// <param name="buffer">The buffer.</param>
/// <param name="offset">The buffer offset.</param>
/// <returns>Converted <see cref="uint" />.</returns>
internal static uint BigEndianToUInt32(byte[] buffer, int offset)
{
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
return BinaryPrimitives.ReadUInt32BigEndian(buffer.AsSpan(offset));
#else
return (uint)buffer[offset + 0] << 24 |
(uint)buffer[offset + 1] << 16 |
(uint)buffer[offset + 2] << 8 |
buffer[offset + 3];
#endif
}
/// <summary>
/// Converts big endian bytes into number.
/// </summary>
/// <param name="buffer">The buffer.</param>
/// <returns>Converted <see cref="uint" />.</returns>
internal static uint BigEndianToUInt32(byte[] buffer)
{
return BigEndianToUInt32(buffer, offset: 0);
}
/// <summary>
/// Converts big endian bytes into number.
/// </summary>
/// <param name="buffer">The buffer.</param>
/// <returns>Converted <see cref="ulong" />.</returns>
internal static ulong BigEndianToUInt64(byte[] buffer)
{
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
return BinaryPrimitives.ReadUInt64BigEndian(buffer);
#else
return (ulong)buffer[0] << 56 |
(ulong)buffer[1] << 48 |
(ulong)buffer[2] << 40 |
(ulong)buffer[3] << 32 |
(ulong)buffer[4] << 24 |
(ulong)buffer[5] << 16 |
(ulong)buffer[6] << 8 |
buffer[7];
#endif
}
}
}
+26 -27
View File
@@ -56,20 +56,41 @@ namespace Renci.SshNet.Common
}
}
#if NET462 || NETSTANDARD2_0
private int Read(Span<byte> buffer)
{
var sharedBuffer = System.Buffers.ArrayPool<byte>.Shared.Rent(buffer.Length);
var numRead = Read(sharedBuffer, 0, buffer.Length);
sharedBuffer.AsSpan(0, numRead).CopyTo(buffer);
System.Buffers.ArrayPool<byte>.Shared.Return(sharedBuffer);
return numRead;
}
private void Write(ReadOnlySpan<byte> buffer)
{
var sharedBuffer = System.Buffers.ArrayPool<byte>.Shared.Rent(buffer.Length);
buffer.CopyTo(sharedBuffer);
Write(sharedBuffer, 0, buffer.Length);
System.Buffers.ArrayPool<byte>.Shared.Return(sharedBuffer);
}
#endif
/// <summary>
/// Writes an <see cref="uint"/> to the SSH data stream.
/// </summary>
/// <param name="value"><see cref="uint"/> data to write.</param>
public void Write(uint value)
{
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
Span<byte> bytes = stackalloc byte[4];
System.Buffers.Binary.BinaryPrimitives.WriteUInt32BigEndian(bytes, value);
Write(bytes);
#else
var bytes = Pack.UInt32ToBigEndian(value);
Write(bytes, 0, bytes.Length);
#endif
}
/// <summary>
@@ -78,14 +99,9 @@ namespace Renci.SshNet.Common
/// <param name="value"><see cref="ulong"/> data to write.</param>
public void Write(ulong value)
{
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
Span<byte> bytes = stackalloc byte[8];
System.Buffers.Binary.BinaryPrimitives.WriteUInt64BigEndian(bytes, value);
Write(bytes);
#else
var bytes = Pack.UInt64ToBigEndian(value);
Write(bytes, 0, bytes.Length);
#endif
}
/// <summary>
@@ -208,14 +224,9 @@ namespace Renci.SshNet.Common
/// </returns>
public ushort ReadUInt16()
{
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
Span<byte> bytes = stackalloc byte[2];
ReadBytes(bytes);
return System.Buffers.Binary.BinaryPrimitives.ReadUInt16BigEndian(bytes);
#else
var data = ReadBytes(2);
return Pack.BigEndianToUInt16(data);
#endif
}
/// <summary>
@@ -226,14 +237,9 @@ namespace Renci.SshNet.Common
/// </returns>
public uint ReadUInt32()
{
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
Span<byte> span = stackalloc byte[4];
ReadBytes(span);
return System.Buffers.Binary.BinaryPrimitives.ReadUInt32BigEndian(span);
#else
var data = ReadBytes(4);
return Pack.BigEndianToUInt32(data);
#endif // NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
}
/// <summary>
@@ -244,14 +250,9 @@ namespace Renci.SshNet.Common
/// </returns>
public ulong ReadUInt64()
{
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
Span<byte> span = stackalloc byte[8];
ReadBytes(span);
return System.Buffers.Binary.BinaryPrimitives.ReadUInt64BigEndian(span);
#else
var data = ReadBytes(8);
return Pack.BigEndianToUInt64(data);
#endif // NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
}
/// <summary>
@@ -316,7 +317,6 @@ namespace Renci.SshNet.Common
return data;
}
#if NETSTANDARD2_1 || NET6_0_OR_GREATER
/// <summary>
/// Reads data into the specified <paramref name="buffer" />.
/// </summary>
@@ -330,6 +330,5 @@ namespace Renci.SshNet.Common
throw new ArgumentOutOfRangeException(nameof(buffer), string.Format(CultureInfo.InvariantCulture, "The requested length ({0}) is greater than the actual number of bytes read ({1}).", buffer.Length, bytesRead));
}
}
#endif // NETSTANDARD2_1 || NET6_0_OR_GREATER
}
}
@@ -1,4 +1,5 @@
using System;
using System.Buffers.Binary;
using System.Net;
using System.Net.Sockets;
using System.Text;
@@ -90,7 +91,7 @@ namespace Renci.SshNet.Connection
connectionRequest[index++] = 0x01; // establish a TCP/IP stream connection
// Port number
Pack.UInt16ToBigEndian(port, connectionRequest, index);
BinaryPrimitives.WriteUInt16BigEndian(connectionRequest.AsSpan(index), port);
index += 2;
// Address
@@ -1,4 +1,5 @@
using System;
using System.Buffers.Binary;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
@@ -239,7 +240,7 @@ namespace Renci.SshNet.Connection
index += addressBytes.Length;
// Port number
Pack.UInt16ToBigEndian(port, connectionRequest, index);
BinaryPrimitives.WriteUInt16BigEndian(connectionRequest.AsSpan(index), port);
return connectionRequest;
}
+3 -2
View File
@@ -1,4 +1,5 @@
using System;
using System.Buffers.Binary;
using System.Globalization;
using System.Linq;
using System.Net;
@@ -479,7 +480,7 @@ namespace Renci.SshNet
return false;
}
var port = Pack.BigEndianToUInt16(portBuffer);
var port = BinaryPrimitives.ReadUInt16BigEndian(portBuffer);
var ipBuffer = new byte[4];
if (SocketAbstraction.Read(socket, ipBuffer, 0, ipBuffer.Length, timeout) == 0)
@@ -602,7 +603,7 @@ namespace Renci.SshNet
return false;
}
var port = Pack.BigEndianToUInt16(portBuffer);
var port = BinaryPrimitives.ReadUInt16BigEndian(portBuffer);
RaiseRequestReceived(host, port);
+1
View File
@@ -37,6 +37,7 @@
<ItemGroup Condition=" '$(TargetFramework)' == 'net462' or '$(TargetFramework)' == 'netstandard2.0' ">
<!-- Must be kept at version 1.0.0 or higher, see https://github.com/sshnet/SSH.NET/pull/1288 for details. -->
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="[1.0.0,)" />
<PackageReference Include="System.Memory" Version="4.5.5" />
</ItemGroup>
<ItemGroup>
@@ -1,6 +1,5 @@
using System;
using Renci.SshNet.Common;
using System.Buffers.Binary;
namespace Renci.SshNet.Security.Cryptography.Ciphers
{
@@ -358,8 +357,8 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
throw new ArgumentException("inputCount");
}
var xl = Pack.BigEndianToUInt32(inputBuffer, inputOffset);
var xr = Pack.BigEndianToUInt32(inputBuffer, inputOffset + 4);
var xl = BinaryPrimitives.ReadUInt32BigEndian(inputBuffer.AsSpan(inputOffset));
var xr = BinaryPrimitives.ReadUInt32BigEndian(inputBuffer.AsSpan(inputOffset + 4));
xl ^= _p[0];
@@ -371,8 +370,8 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
xr ^= _p[Rounds + 1];
Pack.UInt32ToBigEndian(xr, outputBuffer, outputOffset);
Pack.UInt32ToBigEndian(xl, outputBuffer, outputOffset + 4);
BinaryPrimitives.WriteUInt32BigEndian(outputBuffer.AsSpan(outputOffset), xr);
BinaryPrimitives.WriteUInt32BigEndian(outputBuffer.AsSpan(outputOffset + 4), xl);
return BlockSize;
}
@@ -395,8 +394,8 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
throw new ArgumentException("inputCount");
}
var xl = Pack.BigEndianToUInt32(inputBuffer, inputOffset);
var xr = Pack.BigEndianToUInt32(inputBuffer, inputOffset + 4);
var xl = BinaryPrimitives.ReadUInt32BigEndian(inputBuffer.AsSpan(inputOffset));
var xr = BinaryPrimitives.ReadUInt32BigEndian(inputBuffer.AsSpan(inputOffset + 4));
xl ^= _p[Rounds + 1];
@@ -408,8 +407,8 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
xr ^= _p[0];
Pack.UInt32ToBigEndian(xr, outputBuffer, outputOffset);
Pack.UInt32ToBigEndian(xl, outputBuffer, outputOffset + 4);
BinaryPrimitives.WriteUInt32BigEndian(outputBuffer.AsSpan(outputOffset), xr);
BinaryPrimitives.WriteUInt32BigEndian(outputBuffer.AsSpan(outputOffset + 4), xl);
return BlockSize;
}
@@ -1,6 +1,5 @@
using System;
using Renci.SshNet.Common;
using System.Buffers.Binary;
namespace Renci.SshNet.Security.Cryptography.Ciphers
{
@@ -65,15 +64,15 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
* the array is in bytes, the increment is 8x8 bits = 64
*/
var l0 = Pack.BigEndianToUInt32(inputBuffer, inputOffset);
var r0 = Pack.BigEndianToUInt32(inputBuffer, inputOffset + 4);
var l0 = BinaryPrimitives.ReadUInt32BigEndian(inputBuffer.AsSpan(inputOffset));
var r0 = BinaryPrimitives.ReadUInt32BigEndian(inputBuffer.AsSpan(inputOffset + 4));
var result = new uint[2];
CastEncipher(l0, r0, result);
// now stuff them into the destination block
Pack.UInt32ToBigEndian(result[0], outputBuffer, outputOffset);
Pack.UInt32ToBigEndian(result[1], outputBuffer, outputOffset + 4);
BinaryPrimitives.WriteUInt32BigEndian(outputBuffer.AsSpan(outputOffset), result[0]);
BinaryPrimitives.WriteUInt32BigEndian(outputBuffer.AsSpan(outputOffset + 4), result[1]);
return BlockSize;
}
@@ -94,15 +93,15 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
// process the input block
// batch the units up into a 32 bit chunk and go for it
// the array is in bytes, the increment is 8x8 bits = 64
var l16 = Pack.BigEndianToUInt32(inputBuffer, inputOffset);
var r16 = Pack.BigEndianToUInt32(inputBuffer, inputOffset + 4);
var l16 = BinaryPrimitives.ReadUInt32BigEndian(inputBuffer.AsSpan(inputOffset));
var r16 = BinaryPrimitives.ReadUInt32BigEndian(inputBuffer.AsSpan(inputOffset + 4));
var result = new uint[2];
CastDecipher(l16, r16, result);
// now stuff them into the destination block
Pack.UInt32ToBigEndian(result[0], outputBuffer, outputOffset);
Pack.UInt32ToBigEndian(result[1], outputBuffer, outputOffset + 4);
BinaryPrimitives.WriteUInt32BigEndian(outputBuffer.AsSpan(outputOffset), result[0]);
BinaryPrimitives.WriteUInt32BigEndian(outputBuffer.AsSpan(outputOffset + 4), result[1]);
return BlockSize;
}
@@ -1,6 +1,5 @@
using System;
using Renci.SshNet.Common;
using System.Buffers.Binary;
namespace Renci.SshNet.Security.Cryptography.Ciphers
{
@@ -406,8 +405,8 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
/// <param name="outOff">The out off.</param>
protected static void DesFunc(int[] wKey, byte[] input, int inOff, byte[] outBytes, int outOff)
{
var left = Pack.BigEndianToUInt32(input, inOff);
var right = Pack.BigEndianToUInt32(input, inOff + 4);
var left = BinaryPrimitives.ReadUInt32BigEndian(input.AsSpan(inOff));
var right = BinaryPrimitives.ReadUInt32BigEndian(input.AsSpan(inOff + 4));
var work = ((left >> 4) ^ right) & 0x0f0f0f0f;
right ^= work;
@@ -473,8 +472,8 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
left ^= work;
right ^= work << 4;
Pack.UInt32ToBigEndian(right, outBytes, outOff);
Pack.UInt32ToBigEndian(left, outBytes, outOff + 4);
BinaryPrimitives.WriteUInt32BigEndian(outBytes.AsSpan(outOff), right);
BinaryPrimitives.WriteUInt32BigEndian(outBytes.AsSpan(outOff + 4), left);
}
}
}
+4 -3
View File
@@ -1,4 +1,5 @@
using System;
using System.Buffers.Binary;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
@@ -1047,7 +1048,7 @@ namespace Renci.SshNet
var packetDataOffset = 4; // first four bytes are reserved for outbound packet sequence
// write outbound packet sequence to start of packet data
Pack.UInt32ToBigEndian(_outboundPacketSequence, packetData);
BinaryPrimitives.WriteUInt32BigEndian(packetData, _outboundPacketSequence);
if (_clientMac != null && !_clientEtm)
{
@@ -1250,7 +1251,7 @@ namespace Renci.SshNet
firstBlock = _serverCipher.Decrypt(firstBlock);
}
packetLength = Pack.BigEndianToUInt32(firstBlock);
packetLength = BinaryPrimitives.ReadUInt32BigEndian(firstBlock);
// Test packet minimum and maximum boundaries
if (packetLength < Math.Max((byte)16, blockSize) - 4 || packetLength > MaximumSshPacketSize - 4)
@@ -1275,7 +1276,7 @@ namespace Renci.SshNet
// byte[] for the purpose of calculating the client hash. Room for the server MAC is foreseen
// to read the packet including server MAC in a single pass (except for the initial block).
data = new byte[bytesToRead + blockSize + inboundPacketSequenceLength];
Pack.UInt32ToBigEndian(_inboundPacketSequence, data);
BinaryPrimitives.WriteUInt32BigEndian(data, _inboundPacketSequence);
Buffer.BlockCopy(firstBlock, 0, data, inboundPacketSequenceLength, firstBlock.Length);
if (bytesToRead > 0)
@@ -1,187 +0,0 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Renci.SshNet.Common;
namespace Renci.SshNet.Tests.Classes.Common
{
[TestClass]
public class PackTest
{
[TestMethod]
public void BigEndianToUInt16()
{
Assert.AreEqual(0, Pack.BigEndianToUInt16(new byte[] { 0, 0 }));
Assert.AreEqual(1, Pack.BigEndianToUInt16(new byte[] { 0, 1 }));
Assert.AreEqual(256, Pack.BigEndianToUInt16(new byte[] { 1, 0 }));
Assert.AreEqual(257, Pack.BigEndianToUInt16(new byte[] { 1, 1 }));
Assert.AreEqual(1025, Pack.BigEndianToUInt16(new byte[] { 4, 1 }));
Assert.AreEqual(ushort.MaxValue, Pack.BigEndianToUInt16(new byte[] { 255, 255 }));
}
[TestMethod]
public void BigEndianToUInt32()
{
Assert.AreEqual(0U, Pack.BigEndianToUInt32(new byte[] { 0, 0, 0, 0 }));
Assert.AreEqual(1U, Pack.BigEndianToUInt32(new byte[] { 0, 0, 0, 1 }));
Assert.AreEqual(256U, Pack.BigEndianToUInt32(new byte[] { 0, 0, 1, 0 }));
Assert.AreEqual(257U, Pack.BigEndianToUInt32(new byte[] { 0, 0, 1, 1 }));
Assert.AreEqual(1025U, Pack.BigEndianToUInt32(new byte[] { 0, 0, 4, 1 }));
Assert.AreEqual(65536U, Pack.BigEndianToUInt32(new byte[] { 0, 1, 0, 0 }));
Assert.AreEqual(133124U, Pack.BigEndianToUInt32(new byte[] { 0, 2, 8, 4 }));
Assert.AreEqual(16777216U, Pack.BigEndianToUInt32(new byte[] { 1, 0, 0, 0 }));
Assert.AreEqual(uint.MaxValue, Pack.BigEndianToUInt32(new byte[] { 255, 255, 255, 255 }));
}
[TestMethod]
public void BigEndianToUInt64()
{
Assert.AreEqual(0UL, Pack.BigEndianToUInt64(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }));
Assert.AreEqual(1UL, Pack.BigEndianToUInt64(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }));
Assert.AreEqual(256UL, Pack.BigEndianToUInt64(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }));
Assert.AreEqual(257UL, Pack.BigEndianToUInt64(new byte[] { 0, 0, 0, 0, 0, 0, 1, 1 }));
Assert.AreEqual(65536UL, Pack.BigEndianToUInt64(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }));
Assert.AreEqual(133124UL, Pack.BigEndianToUInt64(new byte[] { 0, 0, 0, 0, 0, 2, 8, 4 }));
Assert.AreEqual(16777216UL, Pack.BigEndianToUInt64(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }));
Assert.AreEqual(4294967296UL, Pack.BigEndianToUInt64(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }));
Assert.AreEqual(1099511627776UL, Pack.BigEndianToUInt64(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }));
Assert.AreEqual(1099511892096UL, Pack.BigEndianToUInt64(new byte[] { 0, 0, 1, 0, 0, 4, 8, 128 }));
Assert.AreEqual(1099511627776UL * 256, Pack.BigEndianToUInt64(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }));
Assert.AreEqual(1099511627776UL * 256 * 256, Pack.BigEndianToUInt64(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }));
Assert.AreEqual(ulong.MaxValue, Pack.BigEndianToUInt64(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }));
}
[TestMethod]
public void LittleEndianToUInt16()
{
Assert.AreEqual((ushort)0, Pack.LittleEndianToUInt16(new byte[] { 0, 0 }));
Assert.AreEqual((ushort)1, Pack.LittleEndianToUInt16(new byte[] { 1, 0 }));
Assert.AreEqual((ushort)256, Pack.LittleEndianToUInt16(new byte[] { 0, 1 }));
Assert.AreEqual((ushort)257, Pack.LittleEndianToUInt16(new byte[] { 1, 1 }));
Assert.AreEqual((ushort)1025, Pack.LittleEndianToUInt16(new byte[] { 1, 4 }));
Assert.AreEqual(ushort.MaxValue, Pack.LittleEndianToUInt16(new byte[] { 255, 255 }));
}
[TestMethod]
public void LittleEndianToUInt32()
{
Assert.AreEqual(0U, Pack.LittleEndianToUInt32(new byte[] { 0, 0, 0, 0 }));
Assert.AreEqual(1U, Pack.LittleEndianToUInt32(new byte[] { 1, 0, 0, 0 }));
Assert.AreEqual(256U, Pack.LittleEndianToUInt32(new byte[] { 0, 1, 0, 0 }));
Assert.AreEqual(257U, Pack.LittleEndianToUInt32(new byte[] { 1, 1, 0, 0 }));
Assert.AreEqual(1025U, Pack.LittleEndianToUInt32(new byte[] { 1, 4, 0, 0 }));
Assert.AreEqual(65536U, Pack.LittleEndianToUInt32(new byte[] { 0, 0, 1, 0 }));
Assert.AreEqual(133124U, Pack.LittleEndianToUInt32(new byte[] { 4, 8, 2, 0 }));
Assert.AreEqual(16777216U, Pack.LittleEndianToUInt32(new byte[] { 0, 0, 0, 1 }));
Assert.AreEqual(uint.MaxValue, Pack.LittleEndianToUInt32(new byte[] { 255, 255, 255, 255 }));
}
[TestMethod]
public void LittleEndianToUInt64()
{
Assert.AreEqual(0UL, Pack.LittleEndianToUInt64(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }));
Assert.AreEqual(1UL, Pack.LittleEndianToUInt64(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }));
Assert.AreEqual(256UL, Pack.LittleEndianToUInt64(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }));
Assert.AreEqual(257UL, Pack.LittleEndianToUInt64(new byte[] { 1, 1, 0, 0, 0, 0, 0, 0 }));
Assert.AreEqual(65536UL, Pack.LittleEndianToUInt64(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }));
Assert.AreEqual(133124UL, Pack.LittleEndianToUInt64(new byte[] { 4, 8, 2, 0, 0, 0, 0, 0 }));
Assert.AreEqual(16777216UL, Pack.LittleEndianToUInt64(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }));
Assert.AreEqual(4294967296UL, Pack.LittleEndianToUInt64(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }));
Assert.AreEqual(1099511627776UL, Pack.LittleEndianToUInt64(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }));
Assert.AreEqual(1099511892096UL, Pack.LittleEndianToUInt64(new byte[] { 128, 8, 4, 0, 0, 1, 0, 0 }));
Assert.AreEqual(1099511627776UL * 256, Pack.LittleEndianToUInt64(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }));
Assert.AreEqual(1099511627776UL * 256 * 256, Pack.LittleEndianToUInt64(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }));
Assert.AreEqual(ulong.MaxValue, Pack.LittleEndianToUInt64(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }));
}
[TestMethod]
public void UInt16ToLittleEndian()
{
AssertEqual(new byte[] { 0, 0 }, Pack.UInt16ToLittleEndian(0));
AssertEqual(new byte[] { 1, 0 }, Pack.UInt16ToLittleEndian(1));
AssertEqual(new byte[] { 0, 1 }, Pack.UInt16ToLittleEndian(256));
AssertEqual(new byte[] { 1, 1 }, Pack.UInt16ToLittleEndian(257));
AssertEqual(new byte[] { 1, 4 }, Pack.UInt16ToLittleEndian(1025));
AssertEqual(new byte[] { 255, 255 }, Pack.UInt16ToLittleEndian(ushort.MaxValue));
}
[TestMethod]
public void UInt32ToLittleEndian()
{
AssertEqual(new byte[] { 0, 0, 0, 0 }, Pack.UInt32ToLittleEndian(0));
AssertEqual(new byte[] { 1, 0, 0, 0 }, Pack.UInt32ToLittleEndian(1));
AssertEqual(new byte[] { 0, 1, 0, 0 }, Pack.UInt32ToLittleEndian(256));
AssertEqual(new byte[] { 1, 1, 0, 0 }, Pack.UInt32ToLittleEndian(257));
AssertEqual(new byte[] { 1, 4, 0, 0 }, Pack.UInt32ToLittleEndian(1025));
AssertEqual(new byte[] { 0, 0, 1, 0 }, Pack.UInt32ToLittleEndian(65536));
AssertEqual(new byte[] { 4, 8, 2, 0 }, Pack.UInt32ToLittleEndian(133124));
AssertEqual(new byte[] { 0, 0, 0, 1 }, Pack.UInt32ToLittleEndian(16777216));
AssertEqual(new byte[] { 255, 255, 255, 255 }, Pack.UInt32ToLittleEndian(uint.MaxValue));
}
[TestMethod]
public void UInt64ToLittleEndian()
{
AssertEqual(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, Pack.UInt64ToLittleEndian(0UL));
AssertEqual(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, Pack.UInt64ToLittleEndian(1UL));
AssertEqual(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, Pack.UInt64ToLittleEndian(256UL));
AssertEqual(new byte[] { 1, 1, 0, 0, 0, 0, 0, 0 }, Pack.UInt64ToLittleEndian(257UL));
AssertEqual(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, Pack.UInt64ToLittleEndian(65536UL));
AssertEqual(new byte[] { 4, 8, 2, 0, 0, 0, 0, 0 }, Pack.UInt64ToLittleEndian(133124UL));
AssertEqual(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, Pack.UInt64ToLittleEndian(16777216UL));
AssertEqual(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, Pack.UInt64ToLittleEndian(4294967296UL));
AssertEqual(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, Pack.UInt64ToLittleEndian(1099511627776UL));
AssertEqual(new byte[] { 128, 8, 4, 0, 0, 1, 0, 0 }, Pack.UInt64ToLittleEndian(1099511892096UL));
AssertEqual(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, Pack.UInt64ToLittleEndian(1099511627776UL * 256));
AssertEqual(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, Pack.UInt64ToLittleEndian(1099511627776UL * 256 * 256));
AssertEqual(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, Pack.UInt64ToLittleEndian(ulong.MaxValue));
}
[TestMethod]
public void UInt16ToBigEndian()
{
AssertEqual(new byte[] { 0, 0 }, Pack.UInt16ToBigEndian(0));
AssertEqual(new byte[] { 0, 1 }, Pack.UInt16ToBigEndian(1));
AssertEqual(new byte[] { 1, 0 }, Pack.UInt16ToBigEndian(256));
AssertEqual(new byte[] { 1, 1 }, Pack.UInt16ToBigEndian(257));
AssertEqual(new byte[] { 4, 1 }, Pack.UInt16ToBigEndian(1025));
AssertEqual(new byte[] { 255, 255 }, Pack.UInt16ToBigEndian(ushort.MaxValue));
}
[TestMethod]
public void UInt32ToBigEndian()
{
AssertEqual(new byte[] { 0, 0, 0, 0 }, Pack.UInt32ToBigEndian(0));
AssertEqual(new byte[] { 0, 0, 0, 1 }, Pack.UInt32ToBigEndian(1));
AssertEqual(new byte[] { 0, 0, 1, 0 }, Pack.UInt32ToBigEndian(256));
AssertEqual(new byte[] { 0, 0, 1, 1 }, Pack.UInt32ToBigEndian(257));
AssertEqual(new byte[] { 0, 0, 4, 1 }, Pack.UInt32ToBigEndian(1025));
AssertEqual(new byte[] { 0, 1, 0, 0 }, Pack.UInt32ToBigEndian(65536));
AssertEqual(new byte[] { 0, 2, 8, 4 }, Pack.UInt32ToBigEndian(133124));
AssertEqual(new byte[] { 1, 0, 0, 0 }, Pack.UInt32ToBigEndian(16777216));
AssertEqual(new byte[] { 255, 255, 255, 255 }, Pack.UInt32ToBigEndian(uint.MaxValue));
}
[TestMethod]
public void UInt64ToBigEndian()
{
AssertEqual(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, Pack.UInt64ToBigEndian(0UL));
AssertEqual(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, Pack.UInt64ToBigEndian(1UL));
AssertEqual(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, Pack.UInt64ToBigEndian(256UL));
AssertEqual(new byte[] { 0, 0, 0, 0, 0, 0, 1, 1 }, Pack.UInt64ToBigEndian(257UL));
AssertEqual(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, Pack.UInt64ToBigEndian(65536UL));
AssertEqual(new byte[] { 0, 0, 0, 0, 0, 2, 8, 4 }, Pack.UInt64ToBigEndian(133124UL));
AssertEqual(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, Pack.UInt64ToBigEndian(16777216UL));
AssertEqual(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, Pack.UInt64ToBigEndian(4294967296UL));
AssertEqual(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, Pack.UInt64ToBigEndian(1099511627776UL));
AssertEqual(new byte[] { 0, 0, 1, 0, 0, 4, 8, 128 }, Pack.UInt64ToBigEndian(1099511892096UL));
AssertEqual(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, Pack.UInt64ToBigEndian(1099511627776UL * 256));
AssertEqual(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, Pack.UInt64ToBigEndian(1099511627776UL * 256 * 256));
AssertEqual(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, Pack.UInt64ToBigEndian(ulong.MaxValue));
}
private static void AssertEqual(byte[] expected, byte[] actual)
{
Assert.IsTrue(expected.IsEqualTo(actual));
}
}
}