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"); } } } }
private async Task ProcessClient(HttpListenerContext httpContext) { string ip = httpContext.GetIP(); // Check authentication var authResult = auth.Authenticate(httpContext.Request); if (false == authResult.Success || authResult.ClientID == null) { Log.Debug($"Connection from {ip} denied" + (authResult.ClientID != null ? $" (client ID {authResult.ClientID})" : "")); httpContext.Close(HttpStatusCode.Unauthorized); return; } string clientID = authResult.ClientID; // Accept web socket var clientInfo = RpcPeerInfo.Client(clientID, ip); WebSocketContext context; try { context = await httpContext.AcceptWebSocketAsync(subProtocol : null); Log.Debug($"Connected {clientInfo}"); } catch (Exception ex) { Log.Debug($"Could not accept WebSocket to {clientInfo}: {ex.Message}"); httpContext.Close(HttpStatusCode.InternalServerError); return; } // WebSocket loop WebSocket webSocket = context.WebSocket; try { var connection = new WebSocketRpcConnection(clientInfo, webSocket); var channel = await RpcChannel.Create(clientInfo, connection, this, Settings.Backlog); if (channelsByClientID.TryGetValue(clientID, out var oldChannel)) { Log.Debug($"Channel for client {clientID} was already open; close it and open a new one after 3 seconds."); oldChannel.Stop(); await Task.Delay(3000); } channelsByClientID[clientID] = channel; await channel.Start(); Log.Debug($"Connection to {clientInfo} closed"); } catch (Exception ex) { if (ex is WebSocketException wsEx) { Log.Debug($"Connection to {clientInfo} unexpectedly closed: " + wsEx.WebSocketErrorCode); } else { Log.Debug($"Connection to {clientInfo} unexpectedly closed: " + ex.Message); } } finally { webSocket?.Dispose(); } channelsByClientID.Remove(clientID); }