Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
WebSocketHandle.cs
Go to the documentation of this file.
3using System.IO;
8using System.Text;
11
12namespace System.Net.WebSockets;
13
14internal sealed class WebSocketHandle
15{
16 private sealed class DefaultWebProxy : IWebProxy
17 {
18 public static DefaultWebProxy Instance { get; } = new DefaultWebProxy();
19
20
22 {
23 get
24 {
25 throw new NotSupportedException();
26 }
27 set
28 {
29 throw new NotSupportedException();
30 }
31 }
32
34 {
35 throw new NotSupportedException();
36 }
37
38 public bool IsBypassed(Uri host)
39 {
40 throw new NotSupportedException();
41 }
42 }
43
45
47
48 private WebSocketState _state = WebSocketState.Connecting;
49
51
52 public WebSocket WebSocket { get; private set; }
53
54 public WebSocketState State => WebSocket?.State ?? _state;
55
57 {
58 return new ClientWebSocketOptions
59 {
60 Proxy = DefaultWebProxy.Instance
61 };
62 }
63
64 public void Dispose()
65 {
66 _state = WebSocketState.Closed;
68 }
69
70 public void Abort()
71 {
74 }
75
77 {
79 SocketsHttpHandler handler = null;
80 bool disposeHandler = true;
81 try
82 {
85 if (requestHeaders != null && requestHeaders.Count > 0)
86 {
87 foreach (string requestHeader in options.RequestHeaders)
88 {
89 httpRequestMessage.Headers.TryAddWithoutValidation(requestHeader, options.RequestHeaders[requestHeader]);
90 }
91 }
94 if (options.Credentials == null && !options.UseDefaultCredentials && options.Proxy == null && options.Cookies == null && options.RemoteCertificateValidationCallback == null)
95 {
98 {
99 disposeHandler = false;
100 handler = s_defaultHandler;
101 if (handler == null)
102 {
103 handler = new SocketsHttpHandler
104 {
105 PooledConnectionLifetime = TimeSpan.Zero,
106 UseProxy = false,
107 UseCookies = false
108 };
109 if (Interlocked.CompareExchange(ref s_defaultHandler, handler, null) != null)
110 {
111 handler.Dispose();
112 handler = s_defaultHandler;
113 }
114 }
115 goto IL_02ee;
116 }
117 }
118 handler = new SocketsHttpHandler
119 {
120 PooledConnectionLifetime = TimeSpan.Zero,
121 CookieContainer = options.Cookies,
122 UseCookies = (options.Cookies != null),
123 SslOptions =
124 {
125 RemoteCertificateValidationCallback = options.RemoteCertificateValidationCallback
126 }
127 };
128 if (options.UseDefaultCredentials)
129 {
130 handler.Credentials = CredentialCache.DefaultCredentials;
131 }
132 else
133 {
134 handler.Credentials = options.Credentials;
135 }
136 if (options.Proxy == null)
137 {
138 handler.UseProxy = false;
139 }
140 else if (options.Proxy != DefaultWebProxy.Instance)
141 {
142 handler.Proxy = options.Proxy;
143 }
146 {
147 handler.SslOptions.ClientCertificates = new X509Certificate2Collection();
148 handler.SslOptions.ClientCertificates.AddRange(options.ClientCertificates);
149 }
150 goto IL_02ee;
151 IL_02ee:
154 if (cancellationToken.CanBeCanceled)
155 {
159 }
160 else
161 {
164 }
166 {
168 externalAndAbortCancellation.Token.ThrowIfCancellationRequested();
169 }
170 if (response.StatusCode != HttpStatusCode.SwitchingProtocols)
171 {
173 }
174 ValidateHeader(response.Headers, "Connection", "Upgrade");
175 ValidateHeader(response.Headers, "Upgrade", "websocket");
176 ValidateHeader(response.Headers, "Sec-WebSocket-Accept", secKeyAndSecWebSocketAccept.Value);
177 string text = null;
178 if (response.Headers.TryGetValues("Sec-WebSocket-Protocol", out IEnumerable<string> values))
179 {
180 string[] array = (string[])values;
181 if (array.Length != 0 && !string.IsNullOrEmpty(array[0]))
182 {
183 if (options._requestedSubProtocols != null)
184 {
185 foreach (string requestedSubProtocol in options._requestedSubProtocols)
186 {
187 if (requestedSubProtocol.Equals(array[0], StringComparison.OrdinalIgnoreCase))
188 {
190 break;
191 }
192 }
193 }
194 if (text == null)
195 {
196 throw new WebSocketException(WebSocketError.UnsupportedProtocol, System.SR.Format(System.SR.net_WebSockets_AcceptUnsupportedProtocol, string.Join(", ", options.RequestedSubProtocols), string.Join(", ", array)));
197 }
198 }
199 }
201 if (options.DangerousDeflateOptions != null && response.Headers.TryGetValues("Sec-WebSocket-Extensions", out IEnumerable<string> values2))
202 {
203 foreach (string item in values2)
204 {
206 if (readOnlySpan.TrimStart().StartsWith("permessage-deflate"))
207 {
209 break;
210 }
211 }
212 }
213 if (response.Content == null)
214 {
215 throw new WebSocketException(WebSocketError.ConnectionClosedPrematurely);
216 }
217 Stream stream = response.Content.ReadAsStream();
219 {
220 IsServer = false,
221 SubProtocol = text,
222 KeepAliveInterval = options.KeepAliveInterval,
223 DangerousDeflateOptions = webSocketDeflateOptions
224 });
226 }
227 catch (Exception ex)
228 {
229 if (_state < WebSocketState.Closed)
230 {
231 _state = WebSocketState.Closed;
232 }
233 Abort();
234 response?.Dispose();
235 if (ex is WebSocketException || (ex is OperationCanceledException && cancellationToken.IsCancellationRequested))
236 {
237 throw;
238 }
240 }
241 finally
242 {
243 if (disposeHandler)
244 {
245 handler?.Dispose();
246 }
247 }
248 }
249
251 {
253 while (true)
254 {
255 int num = extension.IndexOf(';');
258 if (num < 0)
259 {
260 span = extension;
261 }
262 else
263 {
265 span = readOnlySpan[..num];
266 }
268 if (readOnlySpan2.Length > 0)
269 {
270 if (readOnlySpan2.SequenceEqual("client_no_context_takeover"))
271 {
272 webSocketDeflateOptions.ClientContextTakeover = false;
273 }
274 else if (readOnlySpan2.SequenceEqual("server_no_context_takeover"))
275 {
276 webSocketDeflateOptions.ServerContextTakeover = false;
277 }
278 else if (readOnlySpan2.StartsWith("client_max_window_bits"))
279 {
280 webSocketDeflateOptions.ClientMaxWindowBits = ParseWindowBits(readOnlySpan2);
281 }
282 else if (readOnlySpan2.StartsWith("server_max_window_bits"))
283 {
284 webSocketDeflateOptions.ServerMaxWindowBits = ParseWindowBits(readOnlySpan2);
285 }
286 }
287 if (num < 0)
288 {
289 break;
290 }
292 extension = readOnlySpan[(num + 1)..];
293 }
294 if (webSocketDeflateOptions.ClientMaxWindowBits > original.ClientMaxWindowBits)
295 {
297 }
298 if (webSocketDeflateOptions.ServerMaxWindowBits > original.ServerMaxWindowBits)
299 {
301 }
304 {
305 int num2 = value.IndexOf('=');
306 if (num2 < 0 || !int.TryParse(value.Slice(num2 + 1), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || result < 9 || result > 15)
307 {
308 throw new WebSocketException(WebSocketError.HeaderError, System.SR.Format(System.SR.net_WebSockets_InvalidResponseHeader, "permessage-deflate", value.ToString()));
309 }
310 return result;
311 }
312 }
313
315 {
316 request.Headers.TryAddWithoutValidation("Connection", "Upgrade");
317 request.Headers.TryAddWithoutValidation("Upgrade", "websocket");
318 request.Headers.TryAddWithoutValidation("Sec-WebSocket-Version", "13");
319 request.Headers.TryAddWithoutValidation("Sec-WebSocket-Key", secKey);
320 List<string> requestedSubProtocols = options._requestedSubProtocols;
322 {
323 request.Headers.TryAddWithoutValidation("Sec-WebSocket-Protocol", string.Join(", ", options.RequestedSubProtocols));
324 }
325 if (options.DangerousDeflateOptions != null)
326 {
327 request.Headers.TryAddWithoutValidation("Sec-WebSocket-Extensions", GetDeflateOptions(options.DangerousDeflateOptions));
328 }
330 {
332 stringBuilder.Append("permessage-deflate").Append("; ");
333 if (options.ClientMaxWindowBits != 15)
334 {
340 handler.AppendFormatted("client_max_window_bits");
341 handler.AppendLiteral("=");
342 handler.AppendFormatted(options.ClientMaxWindowBits);
343 stringBuilder3.Append(provider, ref handler);
344 }
345 else
346 {
347 stringBuilder.Append("client_max_window_bits");
348 }
349 if (!options.ClientContextTakeover)
350 {
351 stringBuilder.Append("; ").Append("client_no_context_takeover");
352 }
353 if (options.ServerMaxWindowBits != 15)
354 {
360 handler2.AppendLiteral("; ");
361 handler2.AppendFormatted("server_max_window_bits");
362 handler2.AppendLiteral("=");
363 handler2.AppendFormatted(options.ServerMaxWindowBits);
365 }
366 if (!options.ServerContextTakeover)
367 {
368 stringBuilder.Append("; ").Append("server_no_context_takeover");
369 }
370 return stringBuilder.ToString();
371 }
372 }
373
375 {
376 ReadOnlySpan<byte> readOnlySpan = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"u8;
377 Span<byte> span = stackalloc byte[24 + readOnlySpan.Length];
378 bool flag = Guid.NewGuid().TryWriteBytes(span);
379 string text = Convert.ToBase64String(span.Slice(0, 16));
380 for (int i = 0; i < text.Length; i++)
381 {
382 span[i] = (byte)text[i];
383 }
384 readOnlySpan.CopyTo(span.Slice(text.Length));
387 }
388
389 private static void ValidateHeader(HttpHeaders headers, string name, string expectedValue)
390 {
391 if (headers.NonValidated.TryGetValues(name, out var values))
392 {
393 if (values.Count == 1)
394 {
396 if (enumerator.MoveNext())
397 {
398 string current = enumerator.Current;
399 if (string.Equals(current, expectedValue, StringComparison.OrdinalIgnoreCase))
400 {
401 return;
402 }
403 }
404 }
406 }
408 }
409}
void CopyTo(KeyValuePair< TKey, TValue >[] array, int index)
static string ToBase64String(byte[] inArray)
Definition Convert.cs:2675
static CultureInfo InvariantCulture
static ICredentials DefaultCredentials
virtual Task< HttpResponseMessage > SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
static HttpMethod Get
Definition HttpMethod.cs:35
SslClientAuthenticationOptions SslOptions
override void Dispose(bool disposing)
static void AddWebSocketHeaders(HttpRequestMessage request, string secKey, ClientWebSocketOptions options)
WebSocketDeflateOptions _negotiatedDeflateOptions
static KeyValuePair< string, string > CreateSecKeyAndSecWebSocketAccept()
static ClientWebSocketOptions CreateDefaultOptions()
static WebSocketDeflateOptions ParseDeflateOptions(ReadOnlySpan< char > extension, WebSocketDeflateOptions original)
static SocketsHttpHandler s_defaultHandler
async Task ConnectAsync(Uri uri, CancellationToken cancellationToken, ClientWebSocketOptions options)
static void ValidateHeader(HttpHeaders headers, string name, string expectedValue)
readonly CancellationTokenSource _abortSource
static WebSocket CreateFromStream(Stream stream, bool isServer, string? subProtocol, TimeSpan keepAliveInterval)
Definition WebSocket.cs:130
static string net_WebSockets_AcceptUnsupportedProtocol
Definition SR.cs:128
static string net_WebSockets_MissingResponseHeader
Definition SR.cs:24
static string net_WebSockets_InvalidResponseHeader
Definition SR.cs:34
static string Format(string resourceFormat, object p1)
Definition SR.cs:118
static string net_WebSockets_ServerWindowBitsNegotiationFailure
Definition SR.cs:40
static string net_WebSockets_ClientWindowBitsNegotiationFailure
Definition SR.cs:42
static string net_webstatus_ConnectFailure
Definition SR.cs:110
static string net_WebSockets_Connect101Expected
Definition SR.cs:22
Definition SR.cs:7
static bool TryHashData(ReadOnlySpan< byte > source, Span< byte > destination, out int bytesWritten)
Definition SHA1.cs:91
static CancellationTokenSource CreateLinkedTokenSource(CancellationToken token1, CancellationToken token2)
static int CompareExchange(ref int location1, int value, int comparand)
static Guid NewGuid()
Definition Guid.cs:1283
static readonly TimeSpan Zero
Definition TimeSpan.cs:21