Remove FromBytes pattern from byte array serializables.
MODIFY
WalletWasabi/Tor/Socks5/Models/Bases/ByteArraySerializableBase.cs
WalletWasabi/Tor/Socks5/Models/Bases/ByteArraySerializableBase.cs
@@ -9,8 +9,6 @@ namespace WalletWasabi.Tor.Socks5.Models.Bases
{
public abstract byte[] ToBytes();
- public abstract void FromBytes(byte[] bytes);
-
public string ToHex(bool xhhSyntax = false)
{
if (xhhSyntax)
@@ -20,14 +18,6 @@ namespace WalletWasabi.Tor.Socks5.Models.Bases
return ByteHelpers.ToHex(ToBytes());
}
- public void FromHex(string hex)
- {
- hex = Guard.NotNullOrEmptyOrWhitespace(nameof(hex), hex, true);
-
- var bytes = ByteHelpers.FromHex(hex);
- FromBytes(bytes);
- }
-
public string ToString(Encoding encoding)
{
Guard.NotNull(nameof(encoding), encoding);

MODIFY
WalletWasabi/Tor/Socks5/Models/Fields/ByteArrayFields/AddrField.cs
WalletWasabi/Tor/Socks5/Models/Fields/ByteArrayFields/AddrField.cs
@@ -11,8 +11,25 @@ namespace WalletWasabi.Tor.Socks5.Models.Fields.ByteArrayFields
{
#region Constructors
- public AddrField()
+ public AddrField(byte[] bytes)
{
+ Bytes = Guard.NotNullOrEmpty(nameof(bytes), bytes);
+
+ AtypField atyp;
+ if (bytes.First() == bytes.Length - 1 && bytes.Length != 4)
+ {
+ atyp = AtypField.DomainName;
+ }
+ else if (bytes.Length == 4)
+ {
+ atyp = AtypField.IPv4;
+ }
+ else
+ {
+ throw new FormatException($"Could not read IPv4 or domain name from {nameof(bytes)}. Value: {bytes}.");
+ }
+
+ Atyp = atyp;
}
/// <param name="dstAddr">Domain or IPv4</param>
@@ -78,9 +95,9 @@ namespace WalletWasabi.Tor.Socks5.Models.Fields.ByteArrayFields
#region PropertiesAndMembers
- private byte[] Bytes { get; set; }
+ private byte[] Bytes { get; }
- public AtypField Atyp { get; set; }
+ public AtypField Atyp { get; }
public string DomainOrIPv4
{
@@ -109,27 +126,6 @@ namespace WalletWasabi.Tor.Socks5.Models.Fields.ByteArrayFields
#region Serialization
- public override void FromBytes(byte[] bytes)
- {
- Bytes = Guard.NotNullOrEmpty(nameof(bytes), bytes);
-
- AtypField atyp;
- if (bytes.First() == bytes.Length - 1 && bytes.Length != 4)
- {
- atyp = AtypField.DomainName;
- }
- else if (bytes.Length == 4)
- {
- atyp = AtypField.IPv4;
- }
- else
- {
- throw new FormatException($"Could not read IPv4 or domain name from {nameof(bytes)}. Value: {bytes}.");
- }
-
- Atyp = atyp;
- }
-
public override byte[] ToBytes() => Bytes;
public override string ToString() => DomainOrIPv4;

MODIFY
WalletWasabi/Tor/Socks5/Models/Fields/ByteArrayFields/MethodsField.cs
WalletWasabi/Tor/Socks5/Models/Fields/ByteArrayFields/MethodsField.cs
@@ -10,8 +10,19 @@ namespace WalletWasabi.Tor.Socks5.Models.Fields.ByteArrayFields
{
#region Constructors
- public MethodsField()
+ public MethodsField(byte[] bytes)
{
+ Guard.NotNullOrEmpty(nameof(bytes), bytes);
+
+ foreach (var b in bytes)
+ {
+ if (b != MethodField.NoAuthenticationRequired && b != MethodField.UsernamePassword)
+ {
+ throw new FormatException($"Unrecognized authentication method: {ByteHelpers.ToHex(b)}.");
+ }
+ }
+
+ Bytes = bytes;
}
public MethodsField(params MethodField[] methods)
@@ -30,7 +41,7 @@ namespace WalletWasabi.Tor.Socks5.Models.Fields.ByteArrayFields
#region PropertiesAndMembers
- private byte[] Bytes { get; set; }
+ private byte[] Bytes { get; }
public IEnumerable<MethodField> Methods
{
@@ -48,21 +59,6 @@ namespace WalletWasabi.Tor.Socks5.Models.Fields.ByteArrayFields
#region Serialization
- public override void FromBytes(byte[] bytes)
- {
- Guard.NotNullOrEmpty(nameof(bytes), bytes);
-
- foreach (var b in bytes)
- {
- if (b != MethodField.NoAuthenticationRequired && b != MethodField.UsernamePassword)
- {
- throw new FormatException($"Unrecognized authentication method: {ByteHelpers.ToHex(b)}.");
- }
- }
-
- Bytes = bytes;
- }
-
public override byte[] ToBytes() => Bytes;
#endregion Serialization

MODIFY
WalletWasabi/Tor/Socks5/Models/Fields/ByteArrayFields/PasswdField.cs
WalletWasabi/Tor/Socks5/Models/Fields/ByteArrayFields/PasswdField.cs
@@ -6,18 +6,20 @@ namespace WalletWasabi.Tor.Socks5.Models.Fields.ByteArrayFields
{
public class PasswdField : ByteArraySerializableBase
{
+ public PasswdField(byte[] bytes)
+ {
+ Bytes = Guard.NotNullOrEmpty(nameof(bytes), bytes);
+ }
+
public PasswdField(string passwd)
+ : this(Encoding.UTF8.GetBytes(passwd))
{
- Guard.NotNullOrEmpty(nameof(passwd), passwd);
- Bytes = Encoding.UTF8.GetBytes(passwd);
}
- private byte[] Bytes { get; set; }
+ private byte[] Bytes { get; }
public string Passwd => Encoding.UTF8.GetString(Bytes); // Tor accepts UTF8 encoded passwd
- public override void FromBytes(byte[] bytes) => Bytes = Guard.NotNullOrEmpty(nameof(bytes), bytes);
-
public override byte[] ToBytes() => Bytes;
}
}

MODIFY
WalletWasabi/Tor/Socks5/Models/Fields/ByteArrayFields/PortField.cs
WalletWasabi/Tor/Socks5/Models/Fields/ByteArrayFields/PortField.cs
@@ -9,8 +9,9 @@ namespace WalletWasabi.Tor.Socks5.Models.Fields.ByteArrayFields
{
#region Constructors
- public PortField()
+ public PortField(byte[] bytes)
{
+ Bytes = Guard.NotNullOrEmpty(nameof(bytes), bytes);
}
public PortField(int dstPort)
@@ -32,7 +33,7 @@ namespace WalletWasabi.Tor.Socks5.Models.Fields.ByteArrayFields
#region PropertiesAndMembers
- private byte[] Bytes { get; set; }
+ private byte[] Bytes { get; }
public int DstPort => BitConverter.ToInt16(Bytes.Reverse().ToArray(), 0);
@@ -40,8 +41,6 @@ namespace WalletWasabi.Tor.Socks5.Models.Fields.ByteArrayFields
#region Serialization
- public override void FromBytes(byte[] bytes) => Bytes = Guard.NotNullOrEmpty(nameof(bytes), bytes);
-
public override byte[] ToBytes() => Bytes;
public override string ToString() => DstPort.ToString();

MODIFY
WalletWasabi/Tor/Socks5/Models/Fields/ByteArrayFields/UNameField.cs
WalletWasabi/Tor/Socks5/Models/Fields/ByteArrayFields/UNameField.cs
@@ -8,21 +8,21 @@ namespace WalletWasabi.Tor.Socks5.Models.Fields.ByteArrayFields
{
#region Constructors
- public UNameField()
+ public UNameField(byte[] bytes)
{
+ Bytes = Guard.NotNullOrEmpty(nameof(bytes), bytes);
}
public UNameField(string uName)
+ : this(Encoding.UTF8.GetBytes(uName))
{
- Guard.NotNullOrEmpty(nameof(uName), uName);
- Bytes = Encoding.UTF8.GetBytes(uName);
}
#endregion Constructors
#region PropertiesAndMembers
- private byte[] Bytes { get; set; }
+ private byte[] Bytes { get; }
public string UName => Encoding.UTF8.GetString(Bytes); // Tor accepts UTF8 encoded passwd
@@ -30,8 +30,6 @@ namespace WalletWasabi.Tor.Socks5.Models.Fields.ByteArrayFields
#region Serialization
- public override void FromBytes(byte[] bytes) => Bytes = Guard.NotNullOrEmpty(nameof(bytes), bytes);
-
public override byte[] ToBytes() => Bytes;
#endregion Serialization

MODIFY
WalletWasabi/Tor/Socks5/Models/Interfaces/IByteArraySerializable.cs
WalletWasabi/Tor/Socks5/Models/Interfaces/IByteArraySerializable.cs
@@ -4,10 +4,6 @@ namespace WalletWasabi.Tor.Socks5.Models.Interfaces
{
byte[] ToBytes();
- void FromBytes(params byte[] bytes);
-
string ToHex(bool xhhSyntax);
-
- void FromHex(string hex);
}
}

MODIFY
WalletWasabi/Tor/Socks5/Models/Messages/MethodSelectionResponse.cs
WalletWasabi/Tor/Socks5/Models/Messages/MethodSelectionResponse.cs
@@ -20,15 +20,6 @@ namespace WalletWasabi.Tor.Socks5.Models.Messages
public MethodField Method { get; }
- public override void FromBytes(byte[] bytes)
- {
- throw new NotSupportedException("This method is no longer supported.");
- }
-
- public override byte[] ToBytes() => new byte[]
- {
- Ver.ToByte(),
- Method.ToByte()
- };
+ public override byte[] ToBytes() => new byte[] { Ver.ToByte(), Method.ToByte() };
}
}

MODIFY
WalletWasabi/Tor/Socks5/Models/Messages/TorSocks5Request.cs
WalletWasabi/Tor/Socks5/Models/Messages/TorSocks5Request.cs
@@ -8,6 +8,26 @@ namespace WalletWasabi.Tor.Socks5.Models.Messages
{
public class TorSocks5Request : ByteArraySerializableBase
{
+ public TorSocks5Request(byte[] bytes)
+ {
+ Guard.NotNullOrEmpty(nameof(bytes), bytes);
+ Guard.MinimumAndNotNull($"{nameof(bytes)}.{nameof(bytes.Length)}", bytes.Length, 6);
+
+ Ver = new VerField(bytes[0]);
+
+ Cmd = new CmdField();
+ Cmd.FromByte(bytes[1]);
+
+ Rsv = new RsvField();
+ Rsv.FromByte(bytes[2]);
+
+ Atyp = new AtypField(bytes[3]);
+
+ DstAddr = new AddrField(bytes[4..^2]);
+
+ DstPort = new PortField(bytes[^2..]);
+ }
+
public TorSocks5Request(CmdField cmd, AddrField dstAddr, PortField dstPort)
{
Cmd = Guard.NotNull(nameof(cmd), cmd);
@@ -20,44 +40,22 @@ namespace WalletWasabi.Tor.Socks5.Models.Messages
#region PropertiesAndMembers
- public VerField Ver { get; set; }
+ public VerField Ver { get; }
- public CmdField Cmd { get; set; }
+ public CmdField Cmd { get; }
- public RsvField Rsv { get; set; }
+ public RsvField Rsv { get; }
- public AtypField Atyp { get; set; }
+ public AtypField Atyp { get; }
- public AddrField DstAddr { get; set; }
+ public AddrField DstAddr { get; }
- public PortField DstPort { get; set; }
+ public PortField DstPort { get; }
#endregion PropertiesAndMembers
#region Serialization
- public override void FromBytes(byte[] bytes)
- {
- Guard.NotNullOrEmpty(nameof(bytes), bytes);
- Guard.MinimumAndNotNull($"{nameof(bytes)}.{nameof(bytes.Length)}", bytes.Length, 6);
-
- Ver = new VerField(bytes[0]);
-
- Cmd = new CmdField();
- Cmd.FromByte(bytes[1]);
-
- Rsv = new RsvField();
- Rsv.FromByte(bytes[2]);
-
- Atyp = new AtypField(bytes[3]);
-
- DstAddr = new AddrField();
- DstAddr.FromBytes(bytes[4..^2]);
-
- DstPort = new PortField();
- DstPort.FromBytes(bytes[^2..]);
- }
-
public override byte[] ToBytes() => ByteHelpers.Combine(new byte[] { Ver.ToByte(), Cmd.ToByte(), Rsv.ToByte(), Atyp.ToByte() }, DstAddr.ToBytes(), DstPort.ToBytes());
#endregion Serialization

MODIFY
WalletWasabi/Tor/Socks5/Models/Messages/TorSocks5Response.cs
WalletWasabi/Tor/Socks5/Models/Messages/TorSocks5Response.cs
@@ -8,23 +8,7 @@ namespace WalletWasabi.Tor.Socks5.Models.Messages
{
public class TorSocks5Response : ByteArraySerializableBase
{
- public TorSocks5Response()
- {
- }
-
- public VerField Ver { get; set; }
-
- public RepField Rep { get; set; }
-
- public RsvField Rsv { get; set; }
-
- public AtypField Atyp { get; set; }
-
- public AddrField BndAddr { get; set; }
-
- public PortField BndPort { get; set; }
-
- public override void FromBytes(byte[] bytes)
+ public TorSocks5Response(byte[] bytes)
{
Guard.NotNullOrEmpty(nameof(bytes), bytes);
Guard.MinimumAndNotNull($"{nameof(bytes)}.{nameof(bytes.Length)}", bytes.Length, 6);
@@ -39,13 +23,23 @@ namespace WalletWasabi.Tor.Socks5.Models.Messages
Atyp = new AtypField(bytes[3]);
- BndAddr = new AddrField();
- BndAddr.FromBytes(bytes[4..^2]);
+ BndAddr = new AddrField(bytes[4..^2]);
- BndPort = new PortField();
- BndPort.FromBytes(bytes[^2..]);
+ BndPort = new PortField(bytes[^2..]);
}
+ public VerField Ver { get; }
+
+ public RepField Rep { get; }
+
+ public RsvField Rsv { get; }
+
+ public AtypField Atyp { get; }
+
+ public AddrField BndAddr { get; }
+
+ public PortField BndPort { get; }
+
public override byte[] ToBytes() => ByteHelpers.Combine(new byte[] { Ver.ToByte(), Rep.ToByte(), Rsv.ToByte(), Atyp.ToByte() }, BndAddr.ToBytes(), BndPort.ToBytes());
}
}

MODIFY
WalletWasabi/Tor/Socks5/Models/Messages/UsernamePasswordRequest.cs
WalletWasabi/Tor/Socks5/Models/Messages/UsernamePasswordRequest.cs
@@ -8,31 +8,7 @@ namespace WalletWasabi.Tor.Socks5.Models.Messages
{
public class UsernamePasswordRequest : ByteArraySerializableBase
{
- public UsernamePasswordRequest(UNameField uName, PasswdField passwd)
- {
- Ver = AuthVerField.Version1;
- UName = Guard.NotNull(nameof(uName), uName);
- Passwd = Guard.NotNull(nameof(passwd), passwd);
-
- var pLen = new PLenField();
- var uLen = new ULenField();
- pLen.FromPasswdField(passwd);
- uLen.FromUNameField(uName);
- PLen = pLen;
- ULen = uLen;
- }
-
- public AuthVerField Ver { get; set; }
-
- public ULenField ULen { get; set; }
-
- public UNameField UName { get; set; }
-
- public PLenField PLen { get; set; }
-
- public PasswdField Passwd { get; set; }
-
- public override void FromBytes(byte[] bytes)
+ public UsernamePasswordRequest(byte[] bytes)
{
Guard.NotNullOrEmpty(nameof(bytes), bytes);
Guard.InRangeAndNotNull($"{nameof(bytes)}.{nameof(bytes.Length)}", bytes.Length, 6, 513);
@@ -42,8 +18,7 @@ namespace WalletWasabi.Tor.Socks5.Models.Messages
ULen = new ULenField();
ULen.FromByte(bytes[1]);
- UName = new UNameField();
- UName.FromBytes(bytes[2..(2 + ULen.Value)]);
+ UName = new UNameField(bytes[2..(2 + ULen.Value)]);
PLen = new PLenField();
PLen.FromByte(bytes[1 + ULen.Value]);
@@ -52,9 +27,33 @@ namespace WalletWasabi.Tor.Socks5.Models.Messages
{
throw new FormatException($"{nameof(PLen)}.{nameof(PLen.Value)} must be {nameof(bytes)}.{nameof(bytes.Length)} - 3 + {nameof(ULen)}.{nameof(ULen.Value)} = {expectedPlenValue}. Actual: {PLen.Value}.");
}
- Passwd.FromBytes(bytes[(3 + ULen.Value)..]);
+ Passwd = new PasswdField(bytes[(3 + ULen.Value)..]);
}
+ public UsernamePasswordRequest(UNameField uName, PasswdField passwd)
+ {
+ Ver = AuthVerField.Version1;
+ UName = Guard.NotNull(nameof(uName), uName);
+ Passwd = Guard.NotNull(nameof(passwd), passwd);
+
+ var pLen = new PLenField();
+ var uLen = new ULenField();
+ pLen.FromPasswdField(passwd);
+ uLen.FromUNameField(uName);
+ PLen = pLen;
+ ULen = uLen;
+ }
+
+ public AuthVerField Ver { get; }
+
+ public ULenField ULen { get; }
+
+ public UNameField UName { get; }
+
+ public PLenField PLen { get; }
+
+ public PasswdField Passwd { get; }
+
public override byte[] ToBytes() => ByteHelpers.Combine(new byte[] { Ver.ToByte(), ULen.ToByte() }, UName.ToBytes(), new byte[] { PLen.ToByte() }, Passwd.ToBytes());
}
}

MODIFY
WalletWasabi/Tor/Socks5/Models/Messages/UsernamePasswordResponse.cs
WalletWasabi/Tor/Socks5/Models/Messages/UsernamePasswordResponse.cs
@@ -20,15 +20,6 @@ namespace WalletWasabi.Tor.Socks5.Models.Messages
public AuthStatusField Status { get; }
- public override void FromBytes(byte[] bytes)
- {
- throw new NotSupportedException("This method is no longer supported.");
- }
-
- public override byte[] ToBytes() => new byte[]
- {
- Ver.ToByte(),
- Status.ToByte()
- };
+ public override byte[] ToBytes() => new byte[] { Ver.ToByte(), Status.ToByte() };
}
}

MODIFY
WalletWasabi/Tor/Socks5/Models/Messages/VersionMethodRequest.cs
WalletWasabi/Tor/Socks5/Models/Messages/VersionMethodRequest.cs
@@ -11,6 +11,22 @@ namespace WalletWasabi.Tor.Socks5.Models.Messages
{
#region Constructors
+ public VersionMethodRequest(byte[] bytes)
+ {
+ Guard.NotNullOrEmpty(nameof(bytes), bytes);
+ Guard.InRangeAndNotNull($"{nameof(bytes)}.{nameof(bytes.Length)}", bytes.Length, 3, 257);
+
+ Ver = new VerField(bytes[0]);
+ NMethods = new NMethodsField(bytes[1]);
+
+ if (NMethods.Value != bytes.Length - 2)
+ {
+ throw new FormatException($"{nameof(NMethods)}.{nameof(NMethods.Value)} must be {nameof(bytes)}.{nameof(bytes.Length)} - 2 = {bytes.Length - 2}. Actual: {NMethods.Value}.");
+ }
+
+ Methods = new MethodsField(bytes.Skip(2).ToArray());
+ }
+
public VersionMethodRequest(MethodsField methods)
{
Methods = Guard.NotNull(nameof(methods), methods);
@@ -25,33 +41,16 @@ namespace WalletWasabi.Tor.Socks5.Models.Messages
#region PropertiesAndMembers
- public VerField Ver { get; set; }
+ public VerField Ver { get; }
- public NMethodsField NMethods { get; set; }
+ public NMethodsField NMethods { get; }
- public MethodsField Methods { get; set; }
+ public MethodsField Methods { get; }
#endregion PropertiesAndMembers
#region Serialization
- public override void FromBytes(byte[] bytes)
- {
- Guard.NotNullOrEmpty(nameof(bytes), bytes);
- Guard.InRangeAndNotNull($"{nameof(bytes)}.{nameof(bytes.Length)}", bytes.Length, 3, 257);
-
- Ver = new VerField(bytes[0]);
- NMethods = new NMethodsField(bytes[1]);
-
- if (NMethods.Value != bytes.Length - 2)
- {
- throw new FormatException($"{nameof(NMethods)}.{nameof(NMethods.Value)} must be {nameof(bytes)}.{nameof(bytes.Length)} - 2 = {bytes.Length - 2}. Actual: {NMethods.Value}.");
- }
-
- Methods = new MethodsField();
- Methods.FromBytes(bytes.Skip(2).ToArray());
- }
-
public override byte[] ToBytes() => ByteHelpers.Combine(
new byte[]
{

MODIFY
WalletWasabi/Tor/Socks5/TorSocks5Client.cs
WalletWasabi/Tor/Socks5/TorSocks5Client.cs
@@ -196,8 +196,7 @@ namespace WalletWasabi.Tor.Socks5
var receiveBuffer = await SendAsync(sendBuffer, receiveBufferSize: null, cancellationToken).ConfigureAwait(false);
- var connectionResponse = new TorSocks5Response();
- connectionResponse.FromBytes(receiveBuffer);
+ var connectionResponse = new TorSocks5Response(receiveBuffer);
if (connectionResponse.Rep != RepField.Succeeded)
{

Remove FromBytes pattern from byte array serializables.