예제 #1
0
    public async Task Connect(string url, CancellationToken ct)
    {
        _client?.Dispose();
        _client = new ClientWebSocket();

        await _client.ConnectAsync(GetConnectionUri(url), ct);
    }
예제 #2
0
        //Asynchronously connect, and return either error or session ID
        public async Task <ConnectResult> Connect(Uri uri)
        {
            Disconnect();

            ws = new ClientWebSocket();
            Console.WriteLine("before ConnectAsync");
            var  cancel      = new CancellationTokenSource();
            Task connectTask = ws.ConnectAsync(uri, cancel.Token);

            if (await Task.WhenAny(connectTask, Task.Delay(2000)) == connectTask &&
                ws.State == WebSocketState.Open)
            {
                Console.WriteLine("connection made, starting rx thread");
                rxThread = new Thread(new ThreadStart(ReceiveThread));
                rxThread.Start();
                return(ConnectResult.Success);
            }
            else
            {
                //connection timed out
                Console.WriteLine($"Failed to connect to server at {uri}");
                cancel.Cancel();
                return(ConnectResult.Failure);
            }
        }
예제 #3
0
        public async Task <bool> ConnectAsync(int port)
        {
            if (_socket != null)
            {
                throw new InvalidOperationException("Already running.");
            }

            try
            {
                _socket = new ClientWebSocket();
                await _socket.ConnectAsync(new Uri($"ws://localhost:{port}"), _cancellationTokenSource.Token);

                while (_socket.State == WebSocketState.Connecting)
                {
                    await Task.Delay(500, _cancellationTokenSource.Token);
                }

                if (_socket.State != WebSocketState.Open)
                {
                    await DisconnectAsync();
                }

                return(true);
            }
            catch (Exception e)
            {
                await DisconnectAsync();

                return(false);
            }
        }
예제 #4
0
        public async Task RunAndBlockAsync(Uri url, CancellationToken cancel)
        {
            var error        = "Error.";
            var bufferWriter = new ArrayBufferWriter <byte>(CHUNK_SIZE);

            try
            {
                using (_ws = new ClientWebSocket())
                {
                    await _ws.ConnectAsync(url, cancel).ConfigureAwait(false);

                    // WebsocketConnected!.Invoke(this);

                    while (true)
                    {
                        var result = await _ws.ReceiveAsync(bufferWriter.GetMemory(CHUNK_SIZE), cancel);

                        bufferWriter.Advance(result.Count);
                        if (result.MessageType == WebSocketMessageType.Close)
                        {
                            var closeMessage = CloseCodes.GetErrorCodeMessage((int?)_ws.CloseStatus ?? 0).Message;
                            error = $"Websocket closed ({_ws.CloseStatus}): {_ws.CloseStatusDescription} {closeMessage}";
                            break;
                        }

                        if (result.EndOfMessage)
                        {
                            var pr   = PayloadReceived;
                            var data = bufferWriter.WrittenMemory.ToArray();
                            bufferWriter.Clear();

                            if (!(pr is null))
                            {
                                await pr.Invoke(data);
                            }
                        }
                    }
                }
            }
            catch (WebSocketException ex)
            {
                Log.Warning("Disconnected, check your internet connection...");
                Log.Debug(ex, "Websocket Exception in websocket client");
            }
            catch (OperationCanceledException)
            {
                // ignored
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error in websocket client. {Message}", ex.Message);
            }
            finally
            {
                bufferWriter.Clear();
                _ws = null;
                await ClosedAsync(error).ConfigureAwait(false);
            }
        }
예제 #5
0
        public async Task ConnectAsync()
        {
            _webSocket?.Dispose();
            _webSocket = new ClientWebSocket();
            _webSocket.Options.SetRequestHeader("Authorization", _configuration.Authorization);

            await _webSocket.ConnectAsync(_url, CancellationToken.None);

            _ = Task.Run(ReceiveAsync);
        }
        public override void Stop()
        {
            if (socket != null)
            {
                socket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
                socket.Dispose();
                socket = null;
            }

            base.Stop();
        }
예제 #7
0
        public Task Close(WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken?cancellationToken = null)
        {
            if (_w == null)
            {
                throw new ObjectDisposedException(nameof(_w));
            }
            var task = _w.CloseAsync(closeStatus, statusDescription, cancellationToken ?? CancellationToken.None);

            _w.Dispose();
            _w = null;
            return(task);
        }
예제 #8
0
        public async Task DisconnectAsync()
        {
            if (_socket == null)
            {
                return;
            }

            ClientWebSocket socket = _socket;

            _socket = null;
            await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Disconnecting", _cancellationTokenSource.Token);

            socket.Dispose();
        }
예제 #9
0
    protected override async Task <WasmDebuggerConnection> SetupConnection(Uri webserverUri, CancellationToken token)
    {
        _clientSocket = await ConnectToWebServer(webserverUri, token);

        ArraySegment <byte> buff = new(new byte[10]);

        _ = _clientSocket.ReceiveAsync(buff, token)
            .ContinueWith(async t =>
        {
            if (token.IsCancellationRequested)
            {
                return;
            }

            logger.LogTrace($"** client socket closed, so stopping the client loop too");
            // Webserver connection is closed
            // So, stop the loop here too
            // _clientInitiatedClose.TrySetResult();
            await Shutdown(token);
        }, TaskContinuationOptions.NotOnRanToCompletion | TaskContinuationOptions.RunContinuationsAsynchronously)
            .ConfigureAwait(false);

        RunLoopStopped += (_, _) =>
        {
            logger.LogDebug($"RunLoop stopped, closing the websocket, state: {_clientSocket.State}");
            if (_clientSocket.State == WebSocketState.Open)
            {
                _clientSocket.Abort();
            }
        };

        IPEndPoint endpoint = new (IPAddress.Parse("127.0.0.1"), DebuggerTestBase.FirefoxProxyPort);

        try
        {
            TcpClient tcpClient = new();

            logger.LogDebug($"Connecting to the proxy at tcp://{endpoint} ..");
            await tcpClient.ConnectAsync(endpoint, token);

            logger.LogDebug($".. connected to the proxy!");
            return(new FirefoxDebuggerConnection(tcpClient, "client", logger));
        }
        catch (SocketException se)
        {
            throw new Exception($"Failed to connect to the proxy at {endpoint}", se);
        }
    }
예제 #10
0
        public override async Task Start()
        {
            while (false == stopper.IsCancellationRequested)
            {
                ClientWebSocket?webSocket = null;
                try {
                    webSocket = new ClientWebSocket();
                    auth.Authenticate(webSocket);
                    await webSocket.ConnectAsync(new Uri(ServerUrl), stopper.Token);

                    Log.Debug($"Connection to server established");
                    serverInfo = RpcPeerInfo.Server(ServerUrl);
                    var connection = new WebSocketRpcConnection(serverInfo, webSocket);
                    channel = await RpcChannel.Create(serverInfo, connection, this, Settings.Backlog);

                    await channel.Start();

                    Log.Debug($"Connection to server closed");
                } catch (Exception ex) {
                    if ((ex as WebSocketException)?.Message.Contains("401") ?? false)
                    {
                        Log.Debug($"Connection to server denied: Unauthorized");
                    }
                    else if (ex is WebSocketException wsEx)
                    {
                        Log.Debug($"Connection to server unexpectedly closed: " + wsEx.WebSocketErrorCode);
                    }
                    else
                    {
                        Log.Debug($"Connection to server unexpectedly closed: " + ex.Message);
                    }
                } finally {
                    webSocket?.Dispose();
                }

                if (false == stopper.IsCancellationRequested)
                {
                    // Reconnect
                    Log.Info($"Trying to reconnect after {Settings.ReconnectTimeMs} ms");
                    await Task.Delay(Settings.ReconnectTimeMs);

                    if (Settings.ReconnectTimeMs >= 30_000) // Repeat logging after a long pause
                    {
                        Log.Info($"Trying to reconnect now");
                    }
                }
            }
        }
        /// <inheritdoc/>
        public async Task <GatewayConnectionResult> DisconnectAsync
        (
            bool reconnectionIntended,
            CancellationToken ct = default
        )
        {
            if (_clientWebSocket is null)
            {
                return(GatewayConnectionResult.FromError("The transport service is not connected."));
            }

            switch (_clientWebSocket.State)
            {
            case WebSocketState.Open:
            case WebSocketState.CloseReceived:
            case WebSocketState.CloseSent:
            {
                try
                {
                    // 1012 is used here instead of normal closure, because close codes 1000 and 1001 don't
                    // allow for reconnection. 1012 is referenced in the websocket protocol as "Service restart",
                    // which makes sense for our use case.
                    var closeCode = reconnectionIntended
                            ? (WebSocketCloseStatus)1012
                            : WebSocketCloseStatus.NormalClosure;

                    await _clientWebSocket.CloseAsync
                    (
                        closeCode,
                        "Terminating connection by user request.",
                        ct
                    );
                }
                catch (WebSocketException)
                {
                    // Most likely due to some kind of premature or forced disconnection; we'll live with it
                }

                break;
            }
            }

            _clientWebSocket.Dispose();
            _clientWebSocket = null;

            this.IsConnected = false;
            return(GatewayConnectionResult.FromSuccess());
        }
        public async Task StartAsync(CancellationToken cancellationToken)
        {
            _cancellationTokenSource = new CancellationTokenSource();
            _webSocket = new ClientWebSocket();
            _id        = 1;

            var uriBuilder = new UriBuilder(new Uri(new Uri(_haConfig.Value.HomeAssistantApi), "api/websocket"));

            uriBuilder.Scheme = uriBuilder.Scheme == Uri.UriSchemeHttps ? "wss" : "ws";

            await _webSocket.ConnectAsync(uriBuilder.Uri, cancellationToken);

            _logger.LogInformation("Connected to home assistant websocket api.");

            _receiveTask = ReceiveAsync();
        }
예제 #13
0
        /// <summary>
        ///     Disposes the inner web socket.
        /// </summary>
        public override void Dispose()
        {
            if (!_initialized || _disposed)
            {
                return;
            }

            _disposed = true;

            _cancellationTokenSource?.Cancel();
            _cancellationTokenSource?.Dispose();
            _webSocket?.Dispose();

            _cancellationTokenSource = null;
            _webSocket = null;

            base.Dispose();
        }
예제 #14
0
        public override async Task StopAsync(CancellationToken cancellationToken)
        {
            await base.StopAsync(cancellationToken);

            if (_webSocket is not null)
            {
                _webSocket.Dispose();
                _webSocket = null;
            }

            if (_heartbeatTask is not null)
            {
                _heartbeatTask.Dispose();
                _heartbeatTask = null;
            }

            _registrations.Clear();

            _logger.LogInformation("Stopped Discord Service");
        }
예제 #15
0
        /// <summary>
        ///     Closes the connection to the remote endpoint asynchronously.
        /// </summary>
        /// <param name="closeStatus">the close status</param>
        /// <param name="reason">the close reason</param>
        /// <param name="cancellationToken">
        ///     a cancellation token used to propagate notification that this operation should be canceled.
        /// </param>
        /// <returns>a task that represents the asynchronously operation.</returns>
        /// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception>
        public async Task CloseAsync(WebSocketCloseStatus closeStatus = WebSocketCloseStatus.Empty, string reason = "", CancellationToken cancellationToken = default)
        {
            EnsureNotDisposed();

            cancellationToken.ThrowIfCancellationRequested();

            if (_webSocket is null)
            {
                throw new InvalidOperationException("Connection not open.");
            }

            // close connection
            await _webSocket.CloseAsync(closeStatus, reason, cancellationToken);

            // dispose web socket
            _webSocket.Dispose();
            _webSocket = null;

            // trigger event
            await OnDisconnectedAsync(new DisconnectedEventArgs(_webSocketUri, closeStatus, reason, false));
        }
        /// <inheritdoc />
        public async Task <GatewayConnectionResult> ConnectAsync(Uri endpoint, CancellationToken ct = default)
        {
            if (_clientWebSocket is not null)
            {
                return(GatewayConnectionResult.FromError("The transport service is already connected."));
            }

            var socket = _services.GetRequiredService <ClientWebSocket>();

            try
            {
                await socket.ConnectAsync(endpoint, ct);

                switch (socket.State)
                {
                case WebSocketState.Open:
                case WebSocketState.Connecting:
                {
                    break;
                }

                default:
                {
                    socket.Dispose();
                    return(GatewayConnectionResult.FromError("Failed to connect to the endpoint."));
                }
                }
            }
            catch (Exception e)
            {
                socket.Dispose();
                return(GatewayConnectionResult.FromError(e));
            }

            _clientWebSocket = socket;

            this.IsConnected = true;
            return(GatewayConnectionResult.FromSuccess());
        }
예제 #17
0
        public async Task ConnectAsync()
        {
            _webSocket = new ClientWebSocket();
            _webSocket.Options.SetRequestHeader("Authorization", _config.Authorization);

            try
            {
                await _webSocket.ConnectAsync(_hostUri, CancellationToken.None);

                if (Log != null)
                {
                    await Log.Invoke(new MessageLoggedEventArgs(_source, LogMessageSeverity.Information, "WebSocket connected"));
                }

                while (_webSocket.State == WebSocketState.Open)
                {
                    var data = await ReceiveAsync();

                    if (DataReceived != null)
                    {
                        await DataReceived.Invoke(data);
                    }
                }
            }
            catch
            {
                //ignored
            }

            _webSocket.Dispose();
            if (Log != null)
            {
                await Log.Invoke(new MessageLoggedEventArgs(_source, LogMessageSeverity.Warning, "The WebSocket was closed or aborted! Attempting reconnect in 1 minute"));
            }

            await Task.Delay(TimeSpan.FromMinutes(1));

            _ = Task.Run(async() => await ConnectAsync());
        }
예제 #18
0
        public override async Task StartAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation("Started Discord Service");
            _logger.LogDebug("Mod role: {ModRole}", _settings.Value.ModRole);


            _webSocket = new ClientWebSocket();

            var url = (await _restApi.GetAsync <GetGatewayResponse>("/gateway", cancellationToken))?.Url ?? string.Empty;

            if (string.IsNullOrWhiteSpace(url))
            {
                _logger.LogError("Unable to get Gateway URL");
                return;
            }

            _logger.LogDebug("Got Gateway Url '{Url}'", url);

            _state     = GatewayState.Connecting;
            _webSocket = new ClientWebSocket();
            await _webSocket.ConnectAsync(new Uri($"{url}?v=9&encoding=json"), cancellationToken);

            await base.StartAsync(cancellationToken);
        }
 protected override async ValueTask ClientHandshakeAsync(CancellationToken token)
 {
     _client = new();
     await _client.ConnectAsync(new(Server), token);
 }
 public WebSocketAdapter(ClientWebSocket?client = null, WebSocket?server = null)
 {
     Assert.True(client is null ^ server is null);
     _client = client;
     _server = server;
 }
예제 #21
0
 public ClientWebSocketWrapper(Uri uri, CancellationToken?cancellationToken = null)
 {
     _w = new ClientWebSocket();
     _w.ConnectAsync(uri, cancellationToken ?? CancellationToken.None).Wait();
 }
예제 #22
0
 protected override IDisposable CreateClient()
 {
     _client = new ClientWebSocket();
     _client.Options.Proxy = WebRequest.DefaultWebProxy;
     return(_client);
 }
 protected override IDisposable CreateClient()
 {
     _client = new();
     return(_client);
 }
예제 #24
0
        /// <summary>
        ///     Processes an incoming payload asynchronously.
        /// </summary>
        /// <remarks>
        ///     This method should not be called manually. It is called in the connection life cycle,
        ///     see: <see cref="RunLifeCycleAsync"/>.
        /// </remarks>
        /// <returns>a task that represents the asynchronous operation</returns>
        /// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception>
        private async Task ProcessNextPayload()
        {
            EnsureNotDisposed();

            WebSocketReceiveResult result;

            try
            {
                result = await _webSocket !.ReceiveAsync(new ArraySegment <byte>(_receiveBuffer, 0, _receiveBuffer.Length), _cancellationTokenSource !.Token);
            }
            catch (WebSocketException ex)
            {
                if (_cancellationTokenSource !.IsCancellationRequested)
                {
                    return;
                }

                Logger?.Log(ex, "Lavalink Node disconnected (without handshake, maybe connection loss or server crash)");
                await OnDisconnectedAsync(new DisconnectedEventArgs(_webSocketUri, WebSocketCloseStatus.Empty, string.Empty, true));

                _webSocket?.Dispose();
                _webSocket = null;
                return;
            }

            // check if the web socket received a close frame
            if (result.MessageType == WebSocketMessageType.Close)
            {
                Logger?.Log(this, string.Format("Lavalink Node disconnected: {0}, {1}.", result.CloseStatus.GetValueOrDefault(), result.CloseStatusDescription), LogLevel.Warning);
                await OnDisconnectedAsync(new DisconnectedEventArgs(_webSocketUri, result.CloseStatus.GetValueOrDefault(), result.CloseStatusDescription, true));

                _webSocket.Dispose();
                _webSocket = null;
                return;
            }

            var content = Encoding.UTF8.GetString(_receiveBuffer, 0, result.Count);

            if (!result.EndOfMessage)
            {
                // the server sent a message frame that is incomplete
                _overflowBuffer.Append(content);
                return;
            }

            // check if old data exists
            if (result.EndOfMessage && _overflowBuffer.Length > 0)
            {
                _overflowBuffer.Append(content);
                content = _overflowBuffer.ToString();
                _overflowBuffer.Clear();
            }

            if (_ioDebug)
            {
                Logger?.Log(this, string.Format("Received payload: `{0}` from: {1}.", content, _webSocketUri), LogLevel.Trace);
            }

            // process data
            try
            {
                var payload   = PayloadConverter.ReadPayload(content);
                var eventArgs = new PayloadReceivedEventArgs(payload, content);
                await OnPayloadReceived(eventArgs);
            }
            catch (Exception ex)
            {
                Logger?.Log(this, string.Format("Received bad payload: {0}.", content), LogLevel.Warning, ex);
                await CloseAsync(WebSocketCloseStatus.InvalidPayloadData);
            }
        }
            static async Task ProcessAsync(WebSocketAdapter webSocket, Behavior behavior, ClientWebSocket?client = null, HttpContext?context = null)
            {
                if (behavior == Behavior.SendsClose_WaitsForClose ||
                    behavior == Behavior.SendsClose_ClosesConnection)
                {
                    await webSocket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "Bye");
                }

                if (behavior == Behavior.SendsClose_WaitsForClose ||
                    behavior == Behavior.WaitsForClose_SendsClose ||
                    behavior == Behavior.WaitsForClose_ClosesConnection)
                {
                    await ReceiveAllMessagesAsync(webSocket);
                }

                if (behavior == Behavior.WaitsForClose_SendsClose)
                {
                    await webSocket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "Bye");
                }

                if (behavior.HasFlag(Behavior.ClosesConnection))
                {
                    client?.Abort();

                    if (context is not null)
                    {
                        await context.Response.Body.FlushAsync();

                        context.Abort();
                    }
                }
            }
예제 #26
0
        /// <summary>
        ///     Connects to the lavalink node asynchronously.
        /// </summary>
        /// <param name="cancellationToken">
        ///     a cancellation token used to propagate notification that the operation should be canceled.
        /// </param>
        /// <returns>a task that represents the asynchronous operation</returns>
        /// <exception cref="InvalidOperationException">
        ///     thrown if the connection is already open
        /// </exception>
        /// <exception cref="OperationCanceledException">thrown if the operation was canceled</exception>
        /// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception>
        public async Task ConnectAsync(CancellationToken cancellationToken = default)
        {
            EnsureNotDisposed();

            cancellationToken.ThrowIfCancellationRequested();

            if (IsConnected)
            {
                throw new InvalidOperationException("Connection is already open.");
            }

            // initialize web-socket and set headers required for the node
            _webSocket = new ClientWebSocket();
            _webSocket.Options.SetRequestHeader("Authorization", _password);
            _webSocket.Options.SetRequestHeader("Num-Shards", _client.ShardCount.ToString());
            _webSocket.Options.SetRequestHeader("User-Id", _client.CurrentUserId.ToString());
            _webSocket.Options.KeepAliveInterval = TimeSpan.FromSeconds(5);

            // add resume header
            if (_resume && _initialized)
            {
                Logger?.Log(this, string.Format("Trying to resume Lavalink Session ... Key: {0}.", ResumeKey), LogLevel.Debug);
                _webSocket.Options.SetRequestHeader("Resume-Key", ResumeKey);
            }

            try
            {
                // connect to the lavalink node
                await _webSocket.ConnectAsync(_webSocketUri, cancellationToken);
            }
            catch (Exception ex)
            {
                if (Logger is null)
                {
                    throw;
                }

                Logger.Log(this, string.Format("Connection to Lavalink Node `{0}` failed!", _webSocketUri), LogLevel.Error, ex);
                return;
            }

            // replay payloads
            if (_queue.Count > 0)
            {
                Logger?.Log(this, string.Format("Replaying {0} payload(s)...", _queue.Count), LogLevel.Debug);

                // replay (FIFO)
                while (_queue.Count > 0)
                {
                    await SendPayloadAsync(_queue.Dequeue());
                }
            }

            // log "Connected"-message
            if (Logger != null)
            {
                var type = _initialized ? "Reconnected" : "Connected";

                if (_resume && _initialized)
                {
                    Logger?.Log(this, string.Format("{0} to Lavalink Node, Resume Key: {1}!", type, ResumeKey));
                }
                else
                {
                    Logger?.Log(this, string.Format("{0} to Lavalink Node!", type));
                }
            }

            // trigger (re)connected event
            await OnConnectedAsync(new ConnectedEventArgs(_webSocketUri, _initialized));

            // resume next session
            _initialized = true;

            // send configure resuming payload
            if (_resume)
            {
                await SendPayloadAsync(new ConfigureResumingPayload(ResumeKey, _sessionTimeout));
            }
        }
예제 #27
0
        public override async Task Start()
        {
            var instance = await instanceGetter;
            var url      = instance?.Urls?.StreamingAPI;

            if (url == null)
            {
                // websocket disabled, fallback to http streaming
                await base.Start();

                return;
            }

            url += "/api/v1/streaming?access_token=" + accessToken;

            switch (streamingType)
            {
            case StreamingType.User:
                url += "&stream=user";
                break;

            case StreamingType.Public:
                url += "&stream=public";
                break;

            case StreamingType.PublicLocal:
                url += "&stream=public:local";
                break;

            case StreamingType.Hashtag:
                url += "&stream=hashtag&tag=" + param;
                break;

            case StreamingType.HashtagLocal:
                url += "&stream=hashtag:local&tag=" + param;
                break;

            case StreamingType.List:
                url += "&stream=list&list=" + param;
                break;

            case StreamingType.Direct:
                url += "&stream=direct";
                break;

            default:
                throw new NotImplementedException();
            }

            socket = new ClientWebSocket();
            await socket.ConnectAsync(new Uri(url), CancellationToken.None);

            byte[]       buffer = new byte[receiveChunkSize];
            MemoryStream ms     = new MemoryStream();

            while (socket != null)
            {
                var result = await socket.ReceiveAsync(new ArraySegment <byte>(buffer), CancellationToken.None);

                ms.Write(buffer, 0, result.Count);

                if (result.EndOfMessage)
                {
                    var messageStr = Encoding.UTF8.GetString(ms.ToArray());

                    var message = JsonConvert.DeserializeObject <Dictionary <string, string> >(messageStr);
                    if (message != null)
                    {
                        var eventName = message["event"];
                        var data      = message["payload"];

                        SendEvent(eventName, data);
                    }
                    else
                    {
                        //SendEvent("", "");
                    }
                    ms.Dispose();
                    ms = new MemoryStream();
                }
            }
            ms.Dispose();

            this.Stop();
        }