public IPCClient(bool autoReconnect = false) { logger = LoggerUtil.GetAppWideLogger(); ipcQueue = new IPCMessageTracker(this); var channel = string.Format("{0}.{1}", nameof(Citadel.IPC), FingerprintService.Default.Value2).ToLower(); client = PlatformTypes.New <IPipeClient>(channel, autoReconnect); // new NamedPipeClient<BaseMessage>(channel); logger.Info("Process {0} creating client", Process.GetCurrentProcess().Id); client.Connected += OnConnected; client.Disconnected += OnDisconnected; client.ServerMessage += OnServerMessage; client.AutoReconnect = autoReconnect; client.Error += clientError; client.Start(); m_callbacks.Add(typeof(IpcMessage), (msg) => { HandleIpcMessage(msg as IpcMessage); }); }
private bool disposedValue = false; // To detect redundant calls protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { client.AutoReconnect = false; client.Stop(); client = null; } // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below. // TODO: set large fields to null. disposedValue = true; } }
public async ValueTask HandleAsync(IDuplexPipe pipe, CancellationToken token = default) { Verify.Operation(Socks5CreateOption is not null, @"You must set {0}", nameof(Socks5CreateOption)); Verify.Operation(Socks5CreateOption.Address is not null, @"You must set socks5 address"); Socks5ServerConnection socks5 = new(pipe, Socks5CreateOption.UsernamePassword); await socks5.AcceptClientAsync(token); AddressType outType = Socks5CreateOption.Address.AddressFamily is AddressFamily.InterNetwork ? AddressType.IPv4 : AddressType.IPv6; switch (socks5.Command) { case Command.Connect: { _logger.LogDebug(@"SOCKS5 Connect"); string target = socks5.Target.Type switch { AddressType.Domain => socks5.Target.Domain !, _ => socks5.Target.Address !.ToString() }; ushort targetPort = socks5.Target.Port; IPipeClient?tmpClient = null; try { tmpClient = await _serversController.GetServerAsync(target, targetPort); } catch (Exception) { tmpClient?.Dispose(); ServerBound failBound = new() { Type = outType, Address = Socks5CreateOption.Address, Port = IPEndPoint.MinPort }; await socks5.SendReplyAsync(Socks5Reply.HostUnreachable, failBound, token); throw; } using IPipeClient client = tmpClient; if (client is ConnectionRefusedTcpClient) { _logger.LogInformation(@"SOCKS5 Connect to {Target}:{Port} Refused", target, targetPort); ServerBound failBound = new() { Type = outType, Address = Socks5CreateOption.Address, Port = IPEndPoint.MinPort }; await socks5.SendReplyAsync(Socks5Reply.ConnectionRefused, failBound, token); break; } _logger.LogInformation(@"SOCKS5 Connect to {Target}:{Port} via {Client}", target, targetPort, client); ServerBound bound = new() { Type = outType, Address = Socks5CreateOption.Address, Port = IPEndPoint.MinPort }; await socks5.SendReplyAsync(Socks5Reply.Succeeded, bound, token); IDuplexPipe clientPipe = client.GetPipe(); await clientPipe.LinkToAsync(pipe, token); break; } case Command.UdpAssociate: { _logger.LogDebug(@"SOCKS5 UdpAssociate"); ServerBound bound = new() { Type = outType, Address = Socks5CreateOption.Address, Port = Socks5CreateOption.Port }; await socks5.SendReplyAsync(Socks5Reply.Succeeded, bound, token); // wait remote close ReadResult result = await pipe.Input.ReadAsync(token); Report.IfNot(result.IsCompleted); break; } default: { ServerBound bound = new() { Type = outType, Address = Socks5CreateOption.Address, Port = IPEndPoint.MinPort }; await socks5.SendReplyAsync(Socks5Reply.CommandNotSupported, bound, token); break; } } } }
public static async Task DataTestAsync <T>(IPipeServer <T> server, IPipeClient <T> client, List <T> values, Func <T, string>?hashFunc = null, CancellationToken cancellationToken = default) { Trace.WriteLine("Setting up test..."); var completionSource = new TaskCompletionSource <bool>(false); // ReSharper disable once AccessToModifiedClosure using var registration = cancellationToken.Register(() => completionSource.TrySetCanceled(cancellationToken)); var actualHash = (string?)null; var clientDisconnected = false; server.ClientConnected += (sender, args) => { Trace.WriteLine("Client connected"); }; server.ClientDisconnected += (sender, args) => { Trace.WriteLine("Client disconnected"); clientDisconnected = true; // ReSharper disable once AccessToModifiedClosure completionSource.TrySetResult(true); }; server.MessageReceived += (sender, args) => { Trace.WriteLine($"Server_OnMessageReceived: {args.Message}"); actualHash = hashFunc?.Invoke(args.Message); Trace.WriteLine($"ActualHash: {actualHash}"); // ReSharper disable once AccessToModifiedClosure completionSource.TrySetResult(true); }; server.ExceptionOccurred += (sender, args) => { Trace.WriteLine($"Server exception occurred: {args.Exception}"); // ReSharper disable once AccessToModifiedClosure completionSource.TrySetException(args.Exception); }; client.Connected += (sender, args) => Trace.WriteLine("Client_OnConnected"); client.Disconnected += (sender, args) => Trace.WriteLine("Client_OnDisconnected"); client.MessageReceived += (sender, args) => Trace.WriteLine($"Client_OnMessageReceived: {args.Message}"); client.ExceptionOccurred += (sender, args) => { Trace.WriteLine($"Client exception occurred: {args.Exception}"); // ReSharper disable once AccessToModifiedClosure completionSource.TrySetException(args.Exception); }; AppDomain.CurrentDomain.UnhandledException += (sender, args) => { if (args.ExceptionObject is Exception exception) { // ReSharper disable once AccessToModifiedClosure completionSource.TrySetException(exception); } }; server.ExceptionOccurred += (sender, args) => Trace.WriteLine(args.Exception.ToString()); client.ExceptionOccurred += (sender, args) => Trace.WriteLine(args.Exception.ToString()); await server.StartAsync(cancellationToken).ConfigureAwait(false); await client.ConnectAsync(cancellationToken).ConfigureAwait(false); Trace.WriteLine("Client and server started"); Trace.WriteLine("---"); var watcher = Stopwatch.StartNew(); foreach (var value in values) { var expectedHash = hashFunc?.Invoke(value); Trace.WriteLine($"ExpectedHash: {expectedHash}"); await client.WriteAsync(value, cancellationToken).ConfigureAwait(false); await completionSource.Task.ConfigureAwait(false); if (hashFunc != null) { Assert.IsNotNull(actualHash, "Server should have received a zero-byte message from the client"); } Assert.AreEqual(expectedHash, actualHash, "SHA-1 hashes for zero-byte message should match"); Assert.IsFalse(clientDisconnected, "Server should not disconnect the client for explicitly sending zero-length data"); Trace.WriteLine("---"); completionSource = new TaskCompletionSource <bool>(false); } Trace.WriteLine($"Test took {watcher.Elapsed}"); Trace.WriteLine("~~~~~~~~~~~~~~~~~~~~~~~~~~"); }