示例#1
0
        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);
            });
        }
示例#2
0
        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;
            }
        }
示例#3
0
    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;
        }
        }
    }
}
示例#4
0
        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("~~~~~~~~~~~~~~~~~~~~~~~~~~");
        }