public bool AllowAutoRedirect { get { throw null; } set { } }
public System.Net.DecompressionMethods AutomaticDecompression { get { throw null; } set { } }
public System.TimeSpan ConnectTimeout { get { throw null; } set { } }
+ [System.Diagnostics.CodeAnalysis.AllowNull]
public System.Net.CookieContainer CookieContainer { get { throw null; } set { } }
public System.Net.ICredentials? Credentials { get { throw null; } set { } }
public System.Net.ICredentials? DefaultProxyCredentials { get { throw null; } set { } }
}
}
+ [AllowNull]
public CookieContainer CookieContainer
{
get => _settings._cookieContainer ?? (_settings._cookieContainer = new CookieContainer());
{
public ClientWebSocket() { }
public override System.Net.WebSockets.WebSocketCloseStatus? CloseStatus { get { throw null; } }
- public override string CloseStatusDescription { get { throw null; } }
+ public override string? CloseStatusDescription { get { throw null; } }
public System.Net.WebSockets.ClientWebSocketOptions Options { get { throw null; } }
public override System.Net.WebSockets.WebSocketState State { get { throw null; } }
- public override string SubProtocol { get { throw null; } }
+ public override string? SubProtocol { get { throw null; } }
public override void Abort() { }
- public override System.Threading.Tasks.Task CloseAsync(System.Net.WebSockets.WebSocketCloseStatus closeStatus, string statusDescription, System.Threading.CancellationToken cancellationToken) { throw null; }
- public override System.Threading.Tasks.Task CloseOutputAsync(System.Net.WebSockets.WebSocketCloseStatus closeStatus, string statusDescription, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public override System.Threading.Tasks.Task CloseAsync(System.Net.WebSockets.WebSocketCloseStatus closeStatus, string? statusDescription, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public override System.Threading.Tasks.Task CloseOutputAsync(System.Net.WebSockets.WebSocketCloseStatus closeStatus, string? statusDescription, System.Threading.CancellationToken cancellationToken) { throw null; }
public System.Threading.Tasks.Task ConnectAsync(System.Uri uri, System.Threading.CancellationToken cancellationToken) { throw null; }
public override void Dispose() { }
public override System.Threading.Tasks.Task<System.Net.WebSockets.WebSocketReceiveResult> ReceiveAsync(System.ArraySegment<byte> buffer, System.Threading.CancellationToken cancellationToken) { throw null; }
{
internal ClientWebSocketOptions() { }
public System.Security.Cryptography.X509Certificates.X509CertificateCollection ClientCertificates { get { throw null; } set { } }
- public System.Net.CookieContainer Cookies { get { throw null; } set { } }
- public System.Net.ICredentials Credentials { get { throw null; } set { } }
+ public System.Net.CookieContainer? Cookies { get { throw null; } set { } }
+ public System.Net.ICredentials? Credentials { get { throw null; } set { } }
public System.TimeSpan KeepAliveInterval { get { throw null; } set { } }
- public System.Net.IWebProxy Proxy { get { throw null; } set { } }
- public System.Net.Security.RemoteCertificateValidationCallback RemoteCertificateValidationCallback { get { throw null; } set { } }
+ public System.Net.IWebProxy? Proxy { get { throw null; } set { } }
+ public System.Net.Security.RemoteCertificateValidationCallback? RemoteCertificateValidationCallback { get { throw null; } set { } }
public bool UseDefaultCredentials { get { throw null; } set { } }
public void AddSubProtocol(string subProtocol) { }
public void SetBuffer(int receiveBufferSize, int sendBufferSize) { }
public void SetBuffer(int receiveBufferSize, int sendBufferSize, System.ArraySegment<byte> buffer) { }
- public void SetRequestHeader(string headerName, string headerValue) { }
+ public void SetRequestHeader(string headerName, string? headerValue) { }
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(NetCoreAppCurrent)</TargetFrameworks>
+ <Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Compile Include="System.Net.WebSockets.Client.cs" />
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<NoWarn>$(NoWarn);CS1573</NoWarn>
<TargetFrameworks>$(NetCoreAppCurrent)-Windows_NT;$(NetCoreAppCurrent)-Unix</TargetFrameworks>
- <Nullable>annotations</Nullable>
+ <Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Compile Include="System\Net\WebSockets\ClientWebSocket.cs" />
}
private readonly ClientWebSocketOptions _options;
- private WebSocketHandle _innerWebSocket; // may be mutable struct; do not make readonly
+ private WebSocketHandle? _innerWebSocket; // may be mutable struct; do not make readonly
// NOTE: this is really an InternalState value, but Interlocked doesn't support
// operations on values of enum types.
}
}
- public override string CloseStatusDescription
+ public override string? CloseStatusDescription
{
get
{
}
}
- public override string SubProtocol
+ public override string? SubProtocol
{
get
{
CancellationToken cancellationToken)
{
ThrowIfNotConnected();
- return _innerWebSocket.SendAsync(buffer, messageType, endOfMessage, cancellationToken);
+ return _innerWebSocket!.SendAsync(buffer, messageType, endOfMessage, cancellationToken);
}
public override ValueTask SendAsync(ReadOnlyMemory<byte> buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken)
{
ThrowIfNotConnected();
- return _innerWebSocket.SendAsync(buffer, messageType, endOfMessage, cancellationToken);
+ return _innerWebSocket!.SendAsync(buffer, messageType, endOfMessage, cancellationToken);
}
public override Task<WebSocketReceiveResult> ReceiveAsync(ArraySegment<byte> buffer,
CancellationToken cancellationToken)
{
ThrowIfNotConnected();
- return _innerWebSocket.ReceiveAsync(buffer, cancellationToken);
+ return _innerWebSocket!.ReceiveAsync(buffer, cancellationToken);
}
public override ValueTask<ValueWebSocketReceiveResult> ReceiveAsync(Memory<byte> buffer, CancellationToken cancellationToken)
{
ThrowIfNotConnected();
- return _innerWebSocket.ReceiveAsync(buffer, cancellationToken);
+ return _innerWebSocket!.ReceiveAsync(buffer, cancellationToken);
}
- public override Task CloseAsync(WebSocketCloseStatus closeStatus, string statusDescription,
- CancellationToken cancellationToken)
+ public override Task CloseAsync(WebSocketCloseStatus closeStatus, string? statusDescription, CancellationToken cancellationToken)
{
ThrowIfNotConnected();
- return _innerWebSocket.CloseAsync(closeStatus, statusDescription, cancellationToken);
+ return _innerWebSocket!.CloseAsync(closeStatus, statusDescription, cancellationToken);
}
- public override Task CloseOutputAsync(WebSocketCloseStatus closeStatus, string statusDescription,
- CancellationToken cancellationToken)
+ public override Task CloseOutputAsync(WebSocketCloseStatus closeStatus, string? statusDescription, CancellationToken cancellationToken)
{
ThrowIfNotConnected();
- return _innerWebSocket.CloseOutputAsync(closeStatus, statusDescription, cancellationToken);
+ return _innerWebSocket!.CloseOutputAsync(closeStatus, statusDescription, cancellationToken);
}
public override void Abort()
internal sealed class DefaultWebProxy : IWebProxy
{
public static DefaultWebProxy Instance { get; } = new DefaultWebProxy();
- public ICredentials Credentials { get => throw new NotSupportedException(); set => throw new NotSupportedException(); }
- public Uri GetProxy(Uri destination) => throw new NotSupportedException();
+ public ICredentials? Credentials { get => throw new NotSupportedException(); set => throw new NotSupportedException(); }
+ public Uri? GetProxy(Uri destination) => throw new NotSupportedException();
public bool IsBypassed(Uri host) => throw new NotSupportedException();
}
}
using System.Collections.Generic;
using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
private bool _isReadOnly; // After ConnectAsync is called the options cannot be modified.
private TimeSpan _keepAliveInterval = WebSocket.DefaultKeepAliveInterval;
private bool _useDefaultCredentials;
- private ICredentials _credentials;
- private IWebProxy _proxy;
- private CookieContainer _cookies;
+ private ICredentials? _credentials;
+ private IWebProxy? _proxy;
+ private CookieContainer? _cookies;
private int _receiveBufferSize = 0x1000;
private ArraySegment<byte>? _buffer;
- private RemoteCertificateValidationCallback _remoteCertificateValidationCallback;
+ private RemoteCertificateValidationCallback? _remoteCertificateValidationCallback;
- internal X509CertificateCollection _clientCertificates;
- internal WebHeaderCollection _requestHeaders;
- internal List<string> _requestedSubProtocols;
+ internal X509CertificateCollection? _clientCertificates;
+ internal WebHeaderCollection? _requestHeaders;
+ internal List<string>? _requestedSubProtocols;
internal ClientWebSocketOptions() { } // prevent external instantiation
#region HTTP Settings
// Note that some headers are restricted like Host.
- public void SetRequestHeader(string headerName, string headerValue)
+ public void SetRequestHeader(string headerName, string? headerValue)
{
ThrowIfReadOnly();
RequestHeaders.Set(headerName, headerValue);
}
- internal WebHeaderCollection RequestHeaders =>
- _requestHeaders ?? (_requestHeaders = new WebHeaderCollection());
+ internal WebHeaderCollection RequestHeaders => _requestHeaders ??= new WebHeaderCollection();
- internal List<string> RequestedSubProtocols =>
- _requestedSubProtocols ?? (_requestedSubProtocols = new List<string>());
+ internal List<string> RequestedSubProtocols => _requestedSubProtocols ??= new List<string>();
public bool UseDefaultCredentials
{
- get
- {
- return _useDefaultCredentials;
- }
+ get => _useDefaultCredentials;
set
{
ThrowIfReadOnly();
}
}
- public ICredentials Credentials
+ public ICredentials? Credentials
{
- get
- {
- return _credentials;
- }
+ get => _credentials;
set
{
ThrowIfReadOnly();
}
}
- public IWebProxy Proxy
+ public IWebProxy? Proxy
{
- get
- {
- return _proxy;
- }
+ get => _proxy;
set
{
ThrowIfReadOnly();
public X509CertificateCollection ClientCertificates
{
- get
- {
- if (_clientCertificates == null)
- {
- _clientCertificates = new X509CertificateCollection();
- }
- return _clientCertificates;
- }
+ get => _clientCertificates ??= new X509CertificateCollection();
set
{
ThrowIfReadOnly();
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
- _clientCertificates = value;
+ _clientCertificates = value ?? throw new ArgumentNullException(nameof(value));
}
}
- public RemoteCertificateValidationCallback RemoteCertificateValidationCallback
+ public RemoteCertificateValidationCallback? RemoteCertificateValidationCallback
{
get => _remoteCertificateValidationCallback;
set
}
}
- public CookieContainer Cookies
+ public CookieContainer? Cookies
{
- get
- {
- return _cookies;
- }
+ get => _cookies;
set
{
ThrowIfReadOnly();
public TimeSpan KeepAliveInterval
{
- get
- {
- return _keepAliveInterval;
- }
+ get => _keepAliveInterval;
set
{
ThrowIfReadOnly();
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
private const string WSServerGuid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
/// <summary>Shared, lazily-initialized handler for when using default options.</summary>
- private static SocketsHttpHandler s_defaultHandler;
+ private static SocketsHttpHandler? s_defaultHandler;
private readonly CancellationTokenSource _abortSource = new CancellationTokenSource();
private WebSocketState _state = WebSocketState.Connecting;
- private WebSocket _webSocket;
+ private WebSocket? _webSocket;
public static WebSocketHandle Create() => new WebSocketHandle();
- public static bool IsValid(WebSocketHandle handle) => handle != null;
+ public static bool IsValid([NotNullWhen(true)] WebSocketHandle? handle) => handle != null;
public WebSocketCloseStatus? CloseStatus => _webSocket?.CloseStatus;
- public string CloseStatusDescription => _webSocket?.CloseStatusDescription;
+ public string? CloseStatusDescription => _webSocket?.CloseStatusDescription;
public WebSocketState State => _webSocket?.State ?? _state;
- public string SubProtocol => _webSocket?.SubProtocol;
+ public string? SubProtocol => _webSocket?.SubProtocol;
public static void CheckPlatformSupport() { /* nop */ }
}
public Task SendAsync(ArraySegment<byte> buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken) =>
- _webSocket.SendAsync(buffer, messageType, endOfMessage, cancellationToken);
+ _webSocket!.SendAsync(buffer, messageType, endOfMessage, cancellationToken);
public ValueTask SendAsync(ReadOnlyMemory<byte> buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken) =>
- _webSocket.SendAsync(buffer, messageType, endOfMessage, cancellationToken);
+ _webSocket!.SendAsync(buffer, messageType, endOfMessage, cancellationToken);
public Task<WebSocketReceiveResult> ReceiveAsync(ArraySegment<byte> buffer, CancellationToken cancellationToken) =>
- _webSocket.ReceiveAsync(buffer, cancellationToken);
+ _webSocket!.ReceiveAsync(buffer, cancellationToken);
public ValueTask<ValueWebSocketReceiveResult> ReceiveAsync(Memory<byte> buffer, CancellationToken cancellationToken) =>
- _webSocket.ReceiveAsync(buffer, cancellationToken);
+ _webSocket!.ReceiveAsync(buffer, cancellationToken);
- public Task CloseAsync(WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken cancellationToken) =>
- _webSocket.CloseAsync(closeStatus, statusDescription, cancellationToken);
+ public Task CloseAsync(WebSocketCloseStatus closeStatus, string? statusDescription, CancellationToken cancellationToken) =>
+ _webSocket!.CloseAsync(closeStatus, statusDescription, cancellationToken);
- public Task CloseOutputAsync(WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken cancellationToken) =>
- _webSocket.CloseOutputAsync(closeStatus, statusDescription, cancellationToken);
+ public Task CloseOutputAsync(WebSocketCloseStatus closeStatus, string? statusDescription, CancellationToken cancellationToken) =>
+ _webSocket!.CloseOutputAsync(closeStatus, statusDescription, cancellationToken);
public async Task ConnectAsyncCore(Uri uri, CancellationToken cancellationToken, ClientWebSocketOptions options)
{
- HttpResponseMessage response = null;
- SocketsHttpHandler handler = null;
+ HttpResponseMessage? response = null;
+ SocketsHttpHandler? handler = null;
bool disposeHandler = true;
try
{
var request = new HttpRequestMessage(HttpMethod.Get, uri);
if (options._requestHeaders?.Count > 0) // use field to avoid lazily initializing the collection
{
- foreach (string key in options.RequestHeaders)
+ foreach (string? key in options.RequestHeaders) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/3214
{
- request.Headers.TryAddWithoutValidation(key, options.RequestHeaders[key]);
+ request.Headers.TryAddWithoutValidation(key!, options.RequestHeaders[key!]);
}
}
}
// Issue the request. The response must be status code 101.
- CancellationTokenSource linkedCancellation, externalAndAbortCancellation;
+ CancellationTokenSource? linkedCancellation;
+ CancellationTokenSource externalAndAbortCancellation;
if (cancellationToken.CanBeCanceled) // avoid allocating linked source if external token is not cancelable
{
linkedCancellation =
// The SecWebSocketProtocol header is optional. We should only get it with a non-empty value if we requested subprotocols,
// and then it must only be one of the ones we requested. If we got a subprotocol other than one we requested (or if we
// already got one in a previous header), fail. Otherwise, track which one we got.
- string subprotocol = null;
- IEnumerable<string> subprotocolEnumerableValues;
- if (response.Headers.TryGetValues(HttpKnownHeaderNames.SecWebSocketProtocol, out subprotocolEnumerableValues))
+ string? subprotocol = null;
+ if (response.Headers.TryGetValues(HttpKnownHeaderNames.SecWebSocketProtocol, out IEnumerable<string>? subprotocolEnumerableValues))
{
Debug.Assert(subprotocolEnumerableValues is string[]);
string[] subprotocolArray = (string[])subprotocolEnumerableValues;
}
}
+ if (response.Content is null)
+ {
+ throw new WebSocketException(WebSocketError.ConnectionClosedPrematurely);
+ }
+
// Get the response stream and wrap it in a web socket.
Stream connectedStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
Debug.Assert(connectedStream.CanWrite);
private static void ValidateHeader(HttpHeaders headers, string name, string expectedValue)
{
- if (!headers.TryGetValues(name, out IEnumerable<string> values))
+ if (!headers.TryGetValues(name, out IEnumerable<string>? values))
{
throw new WebSocketException(WebSocketError.Faulted, SR.Format(SR.net_WebSockets_MissingResponseHeader, name));
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Diagnostics.CodeAnalysis;
-using System.Diagnostics;
-using System.Net;
-using System.Security.Cryptography.X509Certificates;
-using System.Threading;
-using System.Threading.Tasks;
-
-using Microsoft.Win32.SafeHandles;
-
-namespace System.Net.WebSockets
-{
- internal readonly partial struct WebSocketHandle
- {
- #region Properties
- public static bool IsValid(WebSocketHandle handle)
- {
- return handle._webSocket != null;
- }
-
- public WebSocketCloseStatus? CloseStatus
- {
- get
- {
- return _webSocket.CloseStatus;
- }
- }
-
- public string CloseStatusDescription
- {
- get
- {
- return _webSocket.CloseStatusDescription;
- }
- }
-
- public WebSocketState State
- {
- get
- {
- return _webSocket.State;
- }
- }
-
- public string SubProtocol
- {
- get
- {
- return _webSocket.SubProtocol;
- }
- }
- #endregion
-
- public Task SendAsync(
- ArraySegment<byte> buffer,
- WebSocketMessageType messageType,
- bool endOfMessage,
- CancellationToken cancellationToken)
- {
- if (messageType != WebSocketMessageType.Text && messageType != WebSocketMessageType.Binary)
- {
- string errorMessage = SR.Format(
- SR.net_WebSockets_Argument_InvalidMessageType,
- nameof(WebSocketMessageType.Close),
- nameof(SendAsync),
- nameof(WebSocketMessageType.Binary),
- nameof(WebSocketMessageType.Text),
- nameof(CloseOutputAsync));
- throw new ArgumentException(errorMessage, nameof(messageType));
- }
-
- WebSocketValidate.ValidateArraySegment(buffer, nameof(buffer));
-
- return _webSocket.SendAsync(buffer, messageType, endOfMessage, cancellationToken);
- }
-
- public ValueTask SendAsync(ReadOnlyMemory<byte> buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken)
- {
- if (messageType != WebSocketMessageType.Text && messageType != WebSocketMessageType.Binary)
- {
- string errorMessage = SR.Format(
- SR.net_WebSockets_Argument_InvalidMessageType,
- nameof(WebSocketMessageType.Close),
- nameof(SendAsync),
- nameof(WebSocketMessageType.Binary),
- nameof(WebSocketMessageType.Text),
- nameof(CloseOutputAsync));
- throw new ArgumentException(errorMessage, nameof(messageType));
- }
-
- return _webSocket.SendAsync(buffer, messageType, endOfMessage, cancellationToken);
- }
-
- public Task<WebSocketReceiveResult> ReceiveAsync(
- ArraySegment<byte> buffer,
- CancellationToken cancellationToken)
- {
- WebSocketValidate.ValidateArraySegment(buffer, nameof(buffer));
- return _webSocket.ReceiveAsync(buffer, cancellationToken);
- }
-
- public ValueTask<ValueWebSocketReceiveResult> ReceiveAsync(Memory<byte> buffer, CancellationToken cancellationToken) =>
- _webSocket.ReceiveAsync(buffer, cancellationToken);
-
- public Task CloseAsync(
- WebSocketCloseStatus closeStatus,
- string statusDescription,
- CancellationToken cancellationToken)
- {
- WebSocketValidate.ValidateCloseStatus(closeStatus, statusDescription);
- return _webSocket.CloseAsync(closeStatus, statusDescription, cancellationToken);
- }
-
- public Task CloseOutputAsync(
- WebSocketCloseStatus closeStatus,
- string statusDescription,
- CancellationToken cancellationToken)
- {
- WebSocketValidate.ValidateCloseStatus(closeStatus, statusDescription);
- return _webSocket.CloseOutputAsync(closeStatus, statusDescription, cancellationToken);
- }
-
- public void Dispose()
- {
- _webSocket.Dispose();
- }
-
- public void Abort()
- {
- _webSocket.Abort();
- }
- }
-}