public async Task RunAsync(ChannelIdentifier channelIdentifier, WebSocket webSocket, CancellationToken cancellationToken) { if (webSocket == null) { throw new ArgumentNullException(nameof(webSocket)); } var channelOptions = new ConnectorChannelOptions { UseCompression = true }; var channel = new ConnectorChannel(channelOptions, webSocket, _cloudMessageSerializer, _logger); try { var openChannel = new OpenChannel(channelIdentifier, channel, _logger); lock (_openChannels) { _openChannels[channelIdentifier] = openChannel; } await openChannel.RunAsync(cancellationToken).ConfigureAwait(false); } finally { lock (_openChannels) { _openChannels.Remove(channelIdentifier); } } }
async Task ConnectAsync(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { try { _isConnected = false; if (!_storageService.TryReadOrCreate(out _options, DefaultDirectoryNames.Configuration, CloudServiceOptions.Filename) || _options == null) { continue; } if (!_options.IsEnabled) { continue; } if (string.IsNullOrEmpty(_options.ChannelAccessToken)) { continue; } using (var webSocketClient = new ClientWebSocket()) { using (var timeout = new CancellationTokenSource(_options.ReconnectDelay)) { var url = $"wss://{_options.Host}/Connector"; webSocketClient.Options.SetRequestHeader(CloudHeaderNames.ChannelAccessToken, _options.ChannelAccessToken); webSocketClient.Options.SetRequestHeader(CloudHeaderNames.Version, WirehomeCoreVersion.Version); await webSocketClient.ConnectAsync(new Uri(url, UriKind.Absolute), timeout.Token).ConfigureAwait(false); } var channelOptions = new ConnectorChannelOptions { UseCompression = _options.UseCompression }; _channel = new ConnectorChannel(channelOptions, webSocketClient, _cloudMessageSerializer, _logger); _isConnected = true; _connectionError = null; _logger.LogInformation($"Connected with Wirehome.Cloud at host '{_options.Host}'."); while (_channel.IsConnected && !cancellationToken.IsCancellationRequested) { var receiveResult = await _channel.ReceiveAsync(cancellationToken).ConfigureAwait(false); if (receiveResult.CloseConnection || cancellationToken.IsCancellationRequested) { webSocketClient.Abort(); break; } if (receiveResult.Message == null) { continue; } ParallelTask.Start(() => TryProcessCloudMessageAsync(receiveResult.Message, cancellationToken), cancellationToken, _logger); } } } catch (Exception exception) { _connectionError = exception; _logger.LogError(exception, $"Error while connecting with Wirehome.Cloud service at host '{_options?.Host}'."); } finally { _isConnected = false; _channel = null; var delay = TimeSpan.FromSeconds(10); if (_options != null && _options.ReconnectDelay > TimeSpan.Zero) { delay = _options.ReconnectDelay; } await Task.Delay(delay, cancellationToken).ConfigureAwait(false); } } }