Example #1
0
        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();
                }
            }
        }
Example #2
0
 public WriteAsyncResult(WebSocketNetworkStream stream)
 {
     Stream = stream;
 }