private void PipeConnectionReceiveCallback(IAsyncResult ar) { if (_closed) { return; } try { if (connection == null) { return; } int bytesRead = connection.EndReceive(ar); _totalWrite += bytesRead; if (bytesRead > 0) { int atyp = _connetionRecvBuffer[0]; string dst_addr; int dst_port; switch (atyp) { case 1: // IPv4 address, 4 bytes dst_addr = new IPAddress(_connetionRecvBuffer.Skip(1).Take(4).ToArray()).ToString(); dst_port = (_connetionRecvBuffer[5] << 8) + _connetionRecvBuffer[6]; if (_config.isVerboseLogging) { Logging.Info($"connect to {dst_addr}:{dst_port}"); } break; case 3: // domain name, length + str int len = _connetionRecvBuffer[1]; dst_addr = System.Text.Encoding.UTF8.GetString(_connetionRecvBuffer, 2, len); dst_port = (_connetionRecvBuffer[len + 2] << 8) + _connetionRecvBuffer[len + 3]; if (_config.isVerboseLogging) { Logging.Info($"connect to {dst_addr}:{dst_port}"); } break; case 4: // IPv6 address, 16 bytes dst_addr = new IPAddress(_connetionRecvBuffer.Skip(1).Take(16).ToArray()).ToString(); dst_port = (_connetionRecvBuffer[17] << 8) + _connetionRecvBuffer[18]; if (_config.isVerboseLogging) { Logging.Info($"connect to [{dst_addr}]:{dst_port}"); } break; } int bytesToSend; lock (_encryptionLock) { if (_closed) { return; } encryptor.Encrypt(_connetionRecvBuffer, bytesRead, _connetionSendBuffer, out bytesToSend); } _tcprelay.UpdateOutboundCounter(server, bytesToSend); _startSendingTime = DateTime.Now; _bytesToSend = bytesToSend; remote.BeginSend(_connetionSendBuffer, 0, bytesToSend, SocketFlags.None, new AsyncCallback(PipeRemoteSendCallback), null); IStrategy strategy = controller.GetCurrentStrategy(); strategy?.UpdateLastWrite(server); } else { remote.Shutdown(SocketShutdown.Send); _remoteShutdown = true; CheckClose(); } } catch (Exception e) { Logging.LogUsefulException(e); Close(); } }