public async Task ConnectAsyncCore(Uri uri, CancellationToken cancellationToken, ClientWebSocketOptions options)
{
// TODO: Not currently implemented:
// - ClientWebSocketOptions.Credentials
// - ClientWebSocketOptions.Proxy
// Establish connection to the server
CancellationTokenRegistration registration = cancellationToken.Register(s => ((WebSocketHandle)s).Abort(), this);
try
{
// Connect to the remote server
Socket connectedSocket = await ConnectSocketAsync(uri.Host, uri.Port, cancellationToken).ConfigureAwait(false);
Stream stream = new AsyncEventArgsNetworkStream(connectedSocket);
// Upgrade to SSL if needed
if (uri.Scheme == UriScheme.Wss)
{
var sslStream = new SslStream(stream);
await sslStream.AuthenticateAsClientAsync(
uri.Host,
options.ClientCertificates,
SecurityProtocol.AllowedSecurityProtocols,
checkCertificateRevocation: false).ConfigureAwait(false);
stream = sslStream;
}
// Create the security key and expected response, then build all of the request headers
KeyValuePair<string, string> secKeyAndSecWebSocketAccept = CreateSecKeyAndSecWebSocketAccept();
byte[] requestHeader = BuildRequestHeader(uri, options, secKeyAndSecWebSocketAccept.Key);
// Write out the header to the connection
await stream.WriteAsync(requestHeader, 0, requestHeader.Length, cancellationToken).ConfigureAwait(false);
// Parse the response and store our state for the remainder of the connection
string subprotocol = await ParseAndValidateConnectResponseAsync(stream, options, secKeyAndSecWebSocketAccept.Value, cancellationToken).ConfigureAwait(false);
_webSocket = ManagedWebSocket.CreateFromConnectedStream(stream, false, subprotocol);
// If a concurrent Abort or Dispose came in before we set _webSocket, make sure to update it appropriately
if (_state == WebSocketState.Aborted)
{
_webSocket.Abort();
}
else if (_state == WebSocketState.Closed)
{
_webSocket.Dispose();
}
}
catch (Exception exc)
{
if (_state < WebSocketState.Closed)
{
_state = WebSocketState.Closed;
}
Abort();
if (exc is WebSocketException)
{
throw;
}
throw new WebSocketException(SR.net_webstatus_ConnectFailure, exc);
}
finally
{
registration.Dispose();
}
}