protected virtual void Dispose(bool disposing) { if (!Disposed) { if (disposing) { // dispose managed state (managed objects). foreach (var clientPair in Clients) { clientPair.Value.Dispose(); } Clients.Clear(); foreach (var sharkPair in Sharks) { sharkPair.Value.Dispose(); } Sharks.Clear(); } // free unmanaged resources (unmanaged objects) and override a finalizer below. // set large fields to null. Disposed = true; } }
private async void StartClientLoop(TcpClient client) { IProxyClient proxyClient = null; try { var shark = await GetOrCreateSharkClient(); proxyClient = CreateClient(client, shark); var sharkFirstInitialized = false; shark.RemoteClients.Add(proxyClient.Id, proxyClient); Clients.Add(proxyClient.Id, proxyClient); try { var host = await proxyClient.StartAndProcessRequest(); if (!shark.Initialized) { var result = await shark.FastConnect(proxyClient.Id, host); Sharks.Add(shark.Id, shark); sharkFirstInitialized = true; Interlocked.Decrement(ref _waitingCount); await proxyClient.ProcessSharkData(result); } else { await shark.ProxyTo(proxyClient.Id, host); } proxyClient.RemoteDisconnected += OnClientRemoteDisconencted; } catch (AuthenticationException ex) { Logger.LogError(ex, $"Client Auth failed"); shark.Dispose(); Interlocked.Decrement(ref _waitingCount); } catch (Exception ex) { Logger.LogError(ex, $"Process Connect failed for {proxyClient.Id}"); shark.RemoteClients.Remove(proxyClient.Id); Clients.Remove(proxyClient.Id); proxyClient.Dispose(); if (!shark.Initialized) { try { await shark.Auth(); Sharks.Add(shark.Id, shark); sharkFirstInitialized = true; } catch (Exception e) { shark.Dispose(); shark.Logger.LogWarning($"Shark client {shark.Id} initlialize failed, {e} "); throw; } finally { Interlocked.Decrement(ref _waitingCount); } } } if (sharkFirstInitialized) { #pragma warning disable CS4014 StartSharkLoop(shark); #pragma warning restore CS4014 } } catch (Exception) { Logger.LogWarning("Failed to start client loop"); if (proxyClient != null) { proxyClient.Dispose(); } else { try { client.Client.Shutdown(SocketShutdown.Both); client.Client.Disconnect(false); } catch (Exception) { // } client.Dispose(); } } }
protected Task StartSharkLoop(ISharkClient shark) { return(Task.Factory.StartNew(async() => { var taskMap = new Dictionary <int, Task <bool> >(); try { while (true) { var block = await shark.ReadBlock(); shark.DecryptBlock(ref block); if (block.Type == BlockType.DISCONNECT) { var idData = Encoding.UTF8.GetString(block.Data.Span); var ids = JsonSerializer.Deserialize <List <int> >(idData); Logger.LogDebug("Remote request disconnect {0}", idData); foreach (var id in ids) { Clients.TryGetValue(id, out var item); shark.RemoteClients.Remove(id); if (Clients.Remove(id)) { item.Dispose(); item.Logger.LogDebug("Disconnected {0}", id); } else { Logger.LogDebug("Remote request disconnect failed {0}", id); } } continue; } if (Clients.TryGetValue(block.Id, out var client)) { if (taskMap.TryGetValue(block.Id, out var t)) { t = t.ContinueWith(task => { if (!task.IsCompletedSuccessfully || !task.Result) { if (!client.Disposed) { RemoveClient(client); client.Dispose(); taskMap.Remove(block.Id); } return Task.FromResult(false); } return client.ProcessSharkData(block); }).Unwrap(); } else { t = client.ProcessSharkData(block); } taskMap[block.Id] = t; } else { // handle cases taskMap.Remove(block.Id); } } } catch (Exception ex) { Logger.LogError(ex, "Shark error"); } finally { var clients = shark.RemoteClients; foreach (var clientPair in clients) { Clients.Remove(clientPair.Key); clientPair.Value.Dispose(); } Sharks.Remove(shark.Id); shark.Dispose(); taskMap.Clear(); } }).Unwrap()); }