# < Summary

Information

Class: | Renci.SshNet.Connection.Socks4Connector
Assembly: | Renci.SshNet
File(s): | \home\appveyor\projects\ssh-net\src\Renci.SshNet\Connection\Socks4Connector.cs

Line coverage
86%

Covered lines: | 59
Uncovered lines: | 9
Coverable lines: | 68
Total lines: | 135
Line coverage: | 86.7%

Branch coverage
46%

Covered branches: | 6
Total branches: | 13
Branch coverage: | 46.1%

Method coverage

Feature is only available for sponsors

Upgrade to PRO version

# Metrics

Method | Branch coverage | Cyclomatic complexity | Line coverage
--- | --- | --- | ---
.ctor(...) | 100% | 1 | 100%
HandleProxyConnect(...) | 42.85% | 7 | 68.75%
CreateSocks4ConnectionRequest(...) | 100% | 1 | 100%
GetSocks4DestinationAddress(...) | 50% | 4 | 81.81%
GetProxyUserBytes(...) | 50% | 2 | 66.66%

# File(s)

## \home\appveyor\projects\ssh-net\src\Renci.SshNet\Connection\Socks4Connector.cs

| # | Line |  | Line coverage
--- | --- | --- | --- | ---
|  | `1` |  | `using System;`
|  | `2` |  | `using System.Net.Sockets;`
|  | `3` |  | `using System.Text;`
|  | `4` |  | ``
|  | `5` |  | `using Renci.SshNet.Abstractions;`
|  | `6` |  | `using Renci.SshNet.Common;`
|  | `7` |  | ``
|  | `8` |  | `namespace Renci.SshNet.Connection`
|  | `9` |  | `{`
|  | `10` |  | `/// <summary>`
|  | `11` |  | `/// Establishes a tunnel via a SOCKS4 proxy server.`
|  | `12` |  | `/// </summary>`
|  | `13` |  | `/// <remarks>`
|  | `14` |  | `/// https://www.openssh.com/txt/socks4.protocol.`
|  | `15` |  | `/// </remarks>`
|  | `16` |  | `internal sealed class Socks4Connector : ProxyConnector`
|  | `17` |  | `{`
|  | `18` |  | `public Socks4Connector(ISocketFactory socketFactory)`
| 96 | `19` |  | `: base(socketFactory)`
| 96 | `20` |  | `{`
| 96 | `21` |  | `}`
|  | `22` |  | ``
|  | `23` |  | `/// <summary>`
|  | `24` |  | `/// Establishes a connection to the server via a SOCKS5 proxy.`
|  | `25` |  | `/// </summary>`
|  | `26` |  | `/// <param name="connectionInfo">The connection information.</param>`
|  | `27` |  | `/// <param name="socket">The <see cref="Socket"/>.</param>`
|  | `28` |  | `protected override void HandleProxyConnect(IConnectionInfo connectionInfo, Socket socket)`
| 72 | `29` |  | `{`
| 72 | `30` |  | `var connectionRequest = CreateSocks4ConnectionRequest(connectionInfo.Host, (ushort)connectionInfo.Port, conn`
| 72 | `31` |  | `SocketAbstraction.Send(socket, connectionRequest);`
|  | `32` |  | ``
|  | `33` |  | `// Read reply version`
| 72 | `34` |  | `if (SocketReadByte(socket, connectionInfo.Timeout) != 0x00)`
| 0 | `35` |  | `{`
| 0 | `36` |  | `throw new ProxyException("SOCKS4: Null is expected.");`
|  | `37` |  | `}`
|  | `38` |  | ``
|  | `39` |  | `// Read response code`
| 57 | `40` |  | `var code = SocketReadByte(socket, connectionInfo.Timeout);`
|  | `41` |  | ``
| 42 | `42` |  | `switch (code)`
|  | `43` |  | `{`
|  | `44` |  | `case 0x5a:`
| 30 | `45` |  | `break;`
|  | `46` |  | `case 0x5b:`
| 12 | `47` |  | `throw new ProxyException("SOCKS4: Connection rejected.");`
|  | `48` |  | `case 0x5c:`
| 0 | `49` |  | `throw new ProxyException("SOCKS4: Client is not running identd or not reachable from the server.");`
|  | `50` |  | `case 0x5d:`
| 0 | `51` |  | `throw new ProxyException("SOCKS4: Client's identd could not confirm the user ID string in the reques`
|  | `52` |  | `default:`
| 0 | `53` |  | `throw new ProxyException("SOCKS4: Not valid response.");`
|  | `54` |  | `}`
|  | `55` |  | ``
| 30 | `56` |  | `var destBuffer = new byte[6]; // destination port and IP address should be ignored`
| 30 | `57` |  | `_ = SocketRead(socket, destBuffer, 0, destBuffer.Length, connectionInfo.Timeout);`
| 15 | `58` |  | `}`
|  | `59` |  | ``
|  | `60` |  | `private static byte[] CreateSocks4ConnectionRequest(string hostname, ushort port, string username)`
| 72 | `61` |  | `{`
| 72 | `62` |  | `var addressBytes = GetSocks4DestinationAddress(hostname);`
| 72 | `63` |  | `var proxyUserBytes = GetProxyUserBytes(username);`
|  | `64` |  | ``
| 72 | `65` |  | `var connectionRequest = new byte[// SOCKS version number`
| 72 | `66` |  | `1 +`
| 72 | `67` |  | ``
| 72 | `68` |  | `// Command code`
| 72 | `69` |  | `1 +`
| 72 | `70` |  | ``
| 72 | `71` |  | `// Port number`
| 72 | `72` |  | `2 +`
| 72 | `73` |  | ``
| 72 | `74` |  | `// IP address`
| 72 | `75` |  | `addressBytes.Length +`
| 72 | `76` |  | ``
| 72 | `77` |  | `// Username`
| 72 | `78` |  | `proxyUserBytes.Length +`
| 72 | `79` |  | ``
| 72 | `80` |  | `// Null terminator`
| 72 | `81` |  | `1];`
|  | `82` |  | ``
| 72 | `83` |  | `var index = 0;`
|  | `84` |  | ``
|  | `85` |  | `// SOCKS version number`
| 72 | `86` |  | `connectionRequest[index++] = 0x04;`
|  | `87` |  | ``
|  | `88` |  | `// Command code`
| 72 | `89` |  | `connectionRequest[index++] = 0x01; // establish a TCP/IP stream connection`
|  | `90` |  | ``
|  | `91` |  | `// Port number`
| 72 | `92` |  | `Pack.UInt16ToBigEndian(port, connectionRequest, index);`
| 72 | `93` |  | `index += 2;`
|  | `94` |  | ``
|  | `95` |  | `// Address`
| 72 | `96` |  | `Buffer.BlockCopy(addressBytes, 0, connectionRequest, index, addressBytes.Length);`
| 72 | `97` |  | `index += addressBytes.Length;`
|  | `98` |  | ``
|  | `99` |  | `// User name`
| 72 | `100` |  | `Buffer.BlockCopy(proxyUserBytes, 0, connectionRequest, index, proxyUserBytes.Length);`
| 72 | `101` |  | `index += proxyUserBytes.Length;`
|  | `102` |  | ``
|  | `103` |  | `// Null terminator`
| 72 | `104` |  | `connectionRequest[index] = 0x00;`
|  | `105` |  | ``
| 72 | `106` |  | `return connectionRequest;`
| 72 | `107` |  | `}`
|  | `108` |  | ``
|  | `109` |  | `private static byte[] GetSocks4DestinationAddress(string hostname)`
| 72 | `110` |  | `{`
| 72 | `111` |  | `var addresses = DnsAbstraction.GetHostAddresses(hostname);`
|  | `112` |  | ``
| 144 | `113` |  | `for (var i = 0; i < addresses.Length; i++)`
| 72 | `114` |  | `{`
| 72 | `115` |  | `var address = addresses[i];`
| 72 | `116` |  | `if (address.AddressFamily == AddressFamily.InterNetwork)`
| 72 | `117` |  | `{`
| 72 | `118` |  | `return address.GetAddressBytes();`
|  | `119` |  | `}`
| 0 | `120` |  | `}`
|  | `121` |  | ``
| 0 | `122` |  | `throw new ProxyException(string.Format("SOCKS4 only supports IPv4. No such address found for '{0}'.", hostna`
| 72 | `123` |  | `}`
|  | `124` |  | ``
|  | `125` |  | `private static byte[] GetProxyUserBytes(string proxyUser)`
| 72 | `126` |  | `{`
| 72 | `127` |  | `if (proxyUser == null)`
| 0 | `128` |  | `{`
| 0 | `129` |  | `return Array.Empty<byte>();`
|  | `130` |  | `}`
|  | `131` |  | ``
| 72 | `132` |  | `return Encoding.ASCII.GetBytes(proxyUser);`
| 72 | `133` |  | `}`
|  | `134` |  | `}`
|  | `135` |  | `}`

# Methods/Properties

.ctor(Renci.SshNet.Connection.ISocketFactory)
HandleProxyConnect(Renci.SshNet.IConnectionInfo,System.Net.Sockets.Socket)
CreateSocks4ConnectionRequest(System.String,System.UInt16,System.String)
GetSocks4DestinationAddress(System.String)
GetProxyUserBytes(System.String)