public async static Task <WebSocketBase> ConnectAsync(Uri uri, WebSocketClientOptions options = null, CancellationToken cancellationToken = default) { if (uri == null) { throw new ArgumentNullException(nameof(uri)); } if (!uri.IsAbsoluteUri) { throw new ArgumentException("This operation is not supported for a relative uri."); } else if (uri.Scheme != "ws" && uri.Scheme != "wss") { throw new ArgumentException("Only remote addresses starting with 'ws://' or 'wss://' are supported."); } if (options == null) { options = new WebSocketClientOptions(); } // In case of error, we need to do clean up to make sure we don't leak anything Stream connectedSocketStream = null; try { // Connect to the remote server var connectedSocket = await ConnectSocketAsync(uri.Host, uri.Port, cancellationToken).ConfigureAwait(false); connectedSocketStream = new WebSocketNetworkStream(connectedSocket); // Upgrade to SSL if needed if (uri.Scheme == "wss") { connectedSocketStream = new SslStream(connectedSocketStream); await((SslStream)connectedSocketStream).AuthenticateAsClientAsync(uri.Host, null, SslProtocols.Tls11 | SslProtocols.Tls12, checkCertificateRevocation: false).ConfigureAwait(false); } // Create the security key and expected response, then build all of the request headers var secKeyAndSecWebSocketAccept = CreateSecKeyAndSecWebSocketAccept(); var requestHeader = BuildRequestHeader(uri, options.Headers, secKeyAndSecWebSocketAccept.Key, options.EnableMessageCompression); // Write out the header to the connection await connectedSocketStream.WriteAsync(requestHeader, 0, requestHeader.Length, cancellationToken).ConfigureAwait(false); // Parse the response and store our state for the remainder of the connection var responseHeaders = await ParseAndValidateConnectResponseAsync(connectedSocketStream, secKeyAndSecWebSocketAccept.Value, cancellationToken).ConfigureAwait(false); var flags = default(WebSocketFlags); var ip = ((IPEndPoint)connectedSocket.RemoteEndPoint).Address; if (responseHeaders.TryGetValue(WebSocketHeaders.SecWebSocketExtensions, out var extensions) && extensions.IndexOf("permessage-deflate", StringComparison.OrdinalIgnoreCase) >= 0) { flags |= WebSocketFlags.PerMessageDeflate; } var proxy = new WebSocketStreamProxy(connectedSocketStream); connectedSocketStream = null; return(new WebSocket(proxy, flags, ip)); } finally { if (connectedSocketStream != null) { connectedSocketStream.Dispose(); } } }
public WriteAsyncResult(WebSocketNetworkStream stream) { Stream = stream; }