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(); } }