/// <param name="dstAddr">domain or IPv4</param> public AddrField(string dstAddr) { dstAddr = Guard.NotNullOrEmptyOrWhitespace(nameof(dstAddr), dstAddr, true); var atyp = new AtypField(); atyp.FromDstAddr(dstAddr); Atyp = atyp; byte[] bytes; if (atyp == AtypField.DomainName) { // https://www.ietf.org/rfc/rfc1928.txt // the address field contains a fully-qualified domain name. The first // octet of the address field contains the number of octets of name that // follow, there is no terminating NUL octet. var domainBytes = Encoding.ASCII.GetBytes(dstAddr); // Tor only knows ASCII, UTF8 results in general SOCKS server failure var numberOfOctets = domainBytes.Length; if (numberOfOctets > 255) { throw new FormatException($"{nameof(dstAddr)} can be maximum 255 octets. Actual: {numberOfOctets} octets. Value: {dstAddr}."); } bytes = ByteHelpers.Combine(new byte[] { (byte)numberOfOctets }, domainBytes); } else if (atyp == AtypField.IPv4) { // the address is a version-4 IP address, with a length of 4 octets var parts = dstAddr.Split(".", StringSplitOptions.RemoveEmptyEntries); if (parts.Length != 4 || parts.Any(string.IsNullOrWhiteSpace)) { throw new FormatException($"{nameof(dstAddr)} must be have 4 parts. Actual: {parts.Length} parts. Value: {dstAddr}."); } bytes = new byte[4]; for (int i = 0; i < 4; i++) { if (int.TryParse(parts[i], out int partInt)) { if (partInt < 0 || partInt > 255) { throw new FormatException($"Every part of {nameof(dstAddr)} must be between 0 and 255. The {i}. part is invalid: {partInt}. Value of {nameof(dstAddr)}: {dstAddr}"); } bytes[i] = (byte)partInt; } else { throw new FormatException($"Could not parse the {i}. part of {nameof(dstAddr)} to int. Invalid part: {partInt}. Value of {nameof(dstAddr)}: {dstAddr}."); } } } else { throw new NotSupportedException($"{nameof(atyp)} is not supported. Value: {atyp}."); } Bytes = bytes; }
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(bytes[1]); Rsv = new RsvField(bytes[2]); Atyp = new AtypField(bytes[3]); DstAddr = new AddrField(bytes[4..^ 2]);
public TorSocks5Response(byte[] bytes) { Guard.NotNullOrEmpty(nameof(bytes), bytes); Guard.MinimumAndNotNull($"{nameof(bytes)}.{nameof(bytes.Length)}", bytes.Length, smallest: 6); Ver = new VerField(bytes[0]); Rep = new RepField(bytes[1]); Rsv = new RsvField(bytes[2]); Atyp = new AtypField(bytes[3]); BndAddr = new AddrField(bytes[4..^ 2]);
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]); Rep = new RepField(); Rep.FromByte(bytes[1]); Rsv = new RsvField(); Rsv.FromByte(bytes[2]); Atyp = new AtypField(bytes[3]); BndAddr = new AddrField(); BndAddr.FromBytes(bytes[4..^ 2]);
public override void FromBytes(byte[] bytes) { Guard.NotNullOrEmpty(nameof(bytes), bytes); Guard.MinimumAndNotNull($"{nameof(bytes)}.{nameof(bytes.Length)}", bytes.Length, 6); Ver = new VerField(); Ver.FromByte(bytes[0]); Cmd = new CmdField(); Cmd.FromByte(bytes[1]); Rsv = new RsvField(); Rsv.FromByte(bytes[2]); Atyp = new AtypField(); Atyp.FromByte(bytes[3]); DstAddr = new AddrField(); DstAddr.FromBytes(bytes.Skip(4).Take(bytes.Length - 4 - 2).ToArray()); DstPort = new PortField(); DstPort.FromBytes(bytes.Skip(bytes.Length - 2).ToArray()); }