Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
SocksHelper.cs
Go to the documentation of this file.
3using System.IO;
5using System.Text;
8
9namespace System.Net.Http;
10
11internal static class SocksHelper
12{
13 public static async ValueTask EstablishSocksTunnelAsync(Stream stream, string host, int port, Uri proxyUri, ICredentials proxyCredentials, bool async, CancellationToken cancellationToken)
14 {
15 using (cancellationToken.Register(delegate(object s)
16 {
17 ((Stream)s).Dispose();
18 }, stream))
19 {
20 _ = 2;
21 try
22 {
23 NetworkCredential credentials = proxyCredentials?.GetCredential(proxyUri, proxyUri.Scheme);
24 if (string.Equals(proxyUri.Scheme, "socks5", StringComparison.OrdinalIgnoreCase))
25 {
26 await EstablishSocks5TunnelAsync(stream, host, port, proxyUri, credentials, async).ConfigureAwait(continueOnCapturedContext: false);
27 }
28 else if (string.Equals(proxyUri.Scheme, "socks4a", StringComparison.OrdinalIgnoreCase))
29 {
30 await EstablishSocks4TunnelAsync(stream, isVersion4a: true, host, port, proxyUri, credentials, async, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
31 }
32 else if (string.Equals(proxyUri.Scheme, "socks4", StringComparison.OrdinalIgnoreCase))
33 {
34 await EstablishSocks4TunnelAsync(stream, isVersion4a: false, host, port, proxyUri, credentials, async, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
35 }
36 }
37 catch
38 {
39 stream.Dispose();
40 throw;
41 }
42 }
43 }
44
45 private static async ValueTask EstablishSocks5TunnelAsync(Stream stream, string host, int port, Uri proxyUri, NetworkCredential credentials, bool async)
46 {
47 byte[] buffer = ArrayPool<byte>.Shared.Rent(513);
48 try
49 {
50 buffer[0] = 5;
51 if (credentials == null)
52 {
53 buffer[1] = 1;
54 buffer[2] = 0;
55 }
56 else
57 {
58 buffer[1] = 2;
59 buffer[2] = 0;
60 buffer[3] = 2;
61 }
62 await WriteAsync(stream, buffer.AsMemory(0, buffer[1] + 2), async).ConfigureAwait(continueOnCapturedContext: false);
63 await ReadToFillAsync(stream, buffer.AsMemory(0, 2), async).ConfigureAwait(continueOnCapturedContext: false);
65 switch (buffer[1])
66 {
67 case 2:
68 {
69 if (credentials == null)
70 {
72 }
73 buffer[0] = 1;
74 byte b = (buffer[1] = EncodeString(credentials.UserName, buffer.AsSpan(2), "UserName"));
75 await WriteAsync(stream, buffer.AsMemory(0, 3 + b + (buffer[2 + b] = EncodeString(credentials.Password, buffer.AsSpan(3 + b), "Password"))), async).ConfigureAwait(continueOnCapturedContext: false);
76 await ReadToFillAsync(stream, buffer.AsMemory(0, 2), async).ConfigureAwait(continueOnCapturedContext: false);
77 if (buffer[0] != 1 || buffer[1] != 0)
78 {
80 }
81 break;
82 }
83 default:
85 case 0:
86 break;
87 }
88 buffer[0] = 5;
89 buffer[1] = 1;
90 buffer[2] = 0;
91 int num;
92 if (IPAddress.TryParse(host, out IPAddress address))
93 {
94 if (address.AddressFamily == AddressFamily.InterNetwork)
95 {
96 buffer[3] = 1;
97 address.TryWriteBytes(buffer.AsSpan(4), out var _);
98 num = 4;
99 }
100 else
101 {
102 buffer[3] = 4;
103 address.TryWriteBytes(buffer.AsSpan(4), out var _);
104 num = 16;
105 }
106 }
107 else
108 {
109 buffer[3] = 3;
110 num = (buffer[4] = EncodeString(host, buffer.AsSpan(5), "host")) + 1;
111 }
112 BinaryPrimitives.WriteUInt16BigEndian(buffer.AsSpan(num + 4), (ushort)port);
113 await WriteAsync(stream, buffer.AsMemory(0, num + 6), async).ConfigureAwait(continueOnCapturedContext: false);
114 await ReadToFillAsync(stream, buffer.AsMemory(0, 5), async).ConfigureAwait(continueOnCapturedContext: false);
116 if (buffer[1] != 0)
117 {
119 }
120 await ReadToFillAsync(stream, buffer.AsMemory(0, buffer[3] switch
121 {
122 1 => 5,
123 4 => 17,
124 3 => buffer[4] + 2,
125 _ => throw new SocksException(System.SR.net_socks_bad_address_type),
126 }), async).ConfigureAwait(continueOnCapturedContext: false);
127 }
128 finally
129 {
131 }
132 }
133
134 private static async ValueTask EstablishSocks4TunnelAsync(Stream stream, bool isVersion4a, string host, int port, Uri proxyUri, NetworkCredential credentials, bool async, CancellationToken cancellationToken)
135 {
136 byte[] buffer = ArrayPool<byte>.Shared.Rent(513);
137 try
138 {
139 buffer[0] = 4;
140 buffer[1] = 1;
141 BinaryPrimitives.WriteUInt16BigEndian(buffer.AsSpan(2), (ushort)port);
142 IPAddress iPAddress = null;
143 if (IPAddress.TryParse(host, out IPAddress address))
144 {
145 if (address.AddressFamily == AddressFamily.InterNetwork)
146 {
147 iPAddress = address;
148 }
149 else
150 {
151 if (!address.IsIPv4MappedToIPv6)
152 {
154 }
155 iPAddress = address.MapToIPv4();
156 }
157 }
158 else if (!isVersion4a)
159 {
160 IPAddress[] array2;
161 try
162 {
163 IPAddress[] array = ((!async) ? Dns.GetHostAddresses(host, AddressFamily.InterNetwork) : (await Dns.GetHostAddressesAsync(host, AddressFamily.InterNetwork, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)));
164 array2 = array;
165 }
166 catch (Exception innerException)
167 {
168 throw new SocksException(System.SR.net_socks_no_ipv4_address, innerException);
169 }
170 if (array2.Length == 0)
171 {
173 }
174 iPAddress = array2[0];
175 }
176 if (iPAddress == null)
177 {
178 buffer[4] = 0;
179 buffer[5] = 0;
180 buffer[6] = 0;
181 buffer[7] = byte.MaxValue;
182 }
183 else
184 {
185 iPAddress.TryWriteBytes(buffer.AsSpan(4), out var _);
186 }
187 byte b = EncodeString(credentials?.UserName, buffer.AsSpan(8), "UserName");
188 buffer[8 + b] = 0;
189 int num = 9 + b;
190 if (iPAddress == null)
191 {
192 byte b2 = EncodeString(host, buffer.AsSpan(num), "host");
193 buffer[num + b2] = 0;
194 num += b2 + 1;
195 }
196 await WriteAsync(stream, buffer.AsMemory(0, num), async).ConfigureAwait(continueOnCapturedContext: false);
197 await ReadToFillAsync(stream, buffer.AsMemory(0, 8), async).ConfigureAwait(continueOnCapturedContext: false);
198 switch (buffer[1])
199 {
200 case 93:
202 default:
204 case 90:
205 break;
206 }
207 }
208 finally
209 {
211 }
212 }
213
214 private static byte EncodeString(ReadOnlySpan<char> chars, Span<byte> buffer, string parameterName)
215 {
216 try
217 {
218 return checked((byte)Encoding.UTF8.GetBytes(chars, buffer));
219 }
220 catch
221 {
223 }
224 }
225
226 private static void VerifyProtocolVersion(byte expected, byte version)
227 {
228 if (expected != version)
229 {
230 throw new SocksException(System.SR.Format(System.SR.net_socks_unexpected_version, expected, version));
231 }
232 }
233
235 {
236 if (async)
237 {
238 return stream.WriteAsync(buffer);
239 }
240 stream.Write(buffer.Span);
241 return default(ValueTask);
242 }
243
244 private static async ValueTask ReadToFillAsync(Stream stream, Memory<byte> buffer, bool async)
245 {
246 while (buffer.Length != 0)
247 {
248 int num = ((!async) ? stream.Read(buffer.Span) : (await stream.ReadAsync(buffer).ConfigureAwait(continueOnCapturedContext: false)));
249 int num2 = num;
250 if (num2 == 0)
251 {
253 }
254 Memory<byte> memory = buffer;
255 buffer = memory[num2..];
256 }
257 }
258}
static ArrayPool< T > Shared
Definition ArrayPool.cs:7
static void WriteUInt16BigEndian(Span< byte > destination, ushort value)
static Task< IPAddress[]> GetHostAddressesAsync(string hostNameOrAddress)
Definition Dns.cs:205
static IPAddress[] GetHostAddresses(string hostNameOrAddress)
Definition Dns.cs:170
static async ValueTask ReadToFillAsync(Stream stream, Memory< byte > buffer, bool async)
static ValueTask WriteAsync(Stream stream, Memory< byte > buffer, bool async)
static byte EncodeString(ReadOnlySpan< char > chars, Span< byte > buffer, string parameterName)
static async ValueTask EstablishSocks5TunnelAsync(Stream stream, string host, int port, Uri proxyUri, NetworkCredential credentials, bool async)
static async ValueTask EstablishSocksTunnelAsync(Stream stream, string host, int port, Uri proxyUri, ICredentials proxyCredentials, bool async, CancellationToken cancellationToken)
static void VerifyProtocolVersion(byte expected, byte version)
static async ValueTask EstablishSocks4TunnelAsync(Stream stream, bool isVersion4a, string host, int port, Uri proxyUri, NetworkCredential credentials, bool async, CancellationToken cancellationToken)
IPAddress MapToIPv4()
Definition IPAddress.cs:533
bool TryWriteBytes(Span< byte > destination, out int bytesWritten)
Definition IPAddress.cs:334
static bool TryParse([NotNullWhen(true)] string? ipString, [NotNullWhen(true)] out IPAddress? address)
Definition IPAddress.cs:303
static string net_http_invalid_response_premature_eof
Definition SR.cs:94
static string Format(string resourceFormat, object p1)
Definition SR.cs:118
static string net_socks_no_auth_method
Definition SR.cs:218
static string net_socks_ipv6_notsupported
Definition SR.cs:216
static string net_socks_auth_failed
Definition SR.cs:210
static string net_socks_string_too_long
Definition SR.cs:224
static string net_socks_no_ipv4_address
Definition SR.cs:220
static string net_socks_unexpected_version
Definition SR.cs:222
static string net_socks_connection_failed
Definition SR.cs:214
static string net_socks_auth_required
Definition SR.cs:226
Definition SR.cs:7
static Encoding UTF8
Definition Encoding.cs:526
string Scheme
Definition Uri.cs:505
NetworkCredential? GetCredential(Uri uri, string authType)