async Task HandleClient(IClient client, int pipeBufferSize,
                                Action <DuplexPipe> pipeCreatedAction,
                                Func <IPEndPoint, Task <IClient> > createTargetClientFunc,
                                Action <SmartBuffer, DuplexPipe, IClient, ShadowsocksAddress> targetClientConnectedAction,
                                CancellationToken cancellationToken)
        {
            try
            {
                DuplexPipe pipe = new DuplexPipe(pipeBufferSize, _logger);
                pipe.ClientA = client;
                pipeCreatedAction(pipe);///////////////////


                var readClientResult = await pipe.GetReader(client).Read(cancellationToken);//A. Read target addr (and payload).

                if (readClientResult.Result != ReadWriteResult.Succeeded)
                {
                    client.Close(); return;
                }

                if (readClientResult.Read <= 0)
                {
                    _logger?.LogWarning($"This should not happen. [{client.EndPoint.ToString()}]");
                    ////decrypt failed? available options: 1.leave it. 2.close connection. 3.add to blocklist.
                    client.Close();
                    return;
                }
                var request = readClientResult.Memory;

                IPAddress targetIP = IPAddress.Any;                                                          //TODO target address check
                if (ShadowsocksAddress.TryResolve(request.SignificantMemory, out ShadowsocksAddress ssaddr)) //B. Resolve target addr.
                {
                    _logger?.LogWarning($"Reading target addr. ATYP={ssaddr.ATYP}, client=[{client.EndPoint.ToString()}]");
                    IPEndPoint ipeTarget = await ssaddr.ToIPEndPoint();

                    if (IPAddress.Any == ipeTarget.Address || IPAddress.IPv6Any == ipeTarget.Address)//an empty IP.
                    {
                        _logger?.LogWarning($"Invalid target addr. client=[{client.EndPoint.ToString()}]");
                        client.Close();
                        return;
                    }

                    _logger?.LogInformation($"Resolved target address:[{ipeTarget.ToString()}]. Connecting...");
                    IClient targetClient = await createTargetClientFunc(ipeTarget); //C. Connect target ///////////////////////////////

                    if (null == targetClient)                                       //connect target failed.
                    {
                        _logger?.LogInformation($"Unable to connect target [{ipeTarget.ToString()}]. client=[{client.EndPoint.ToString()}]");
                        client.Close();
                        return;
                    }
                    _logger?.LogInformation($"Connected to [{ipeTarget.ToString()}]");
                    targetClientConnectedAction(request, pipe, targetClient, ssaddr);////////////////////////////////

                    _logger?.LogInformation($"Start piping...");
                    PipeClient(pipe, cancellationToken);//D. start piping.
                }
                else//invalid socks5 addr
                {
                    _logger?.LogWarning($"Resolve target addr failed. client=[{client.EndPoint.ToString()}]");
                    client.Close();
                    return;
                }

                await Task.CompletedTask;
            }
            catch (Exception ex)
            {
                _logger?.LogError(ex, "HandleClient");
            }
        }