diff --git a/shadowsocks-csharp/Controller/Service/TCPRelay.cs b/shadowsocks-csharp/Controller/Service/TCPRelay.cs index 8f382c78..ae62250e 100644 --- a/shadowsocks-csharp/Controller/Service/TCPRelay.cs +++ b/shadowsocks-csharp/Controller/Service/TCPRelay.cs @@ -35,10 +35,7 @@ namespace Shadowsocks.Controller || (length < 2 || firstPacket[0] != 5)) return false; socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); - TCPHandler handler = new TCPHandler(this, _config); - handler.connection = socket; - handler.controller = _controller; - handler.tcprelay = this; + TCPHandler handler = new TCPHandler(_controller, _config, this, socket); handler.Start(firstPacket, length); IList handlersToClose = new List(); @@ -122,68 +119,67 @@ namespace Shadowsocks.Controller public static readonly int RecvReserveSize = IVEncryptor.ONETIMEAUTH_BYTES + IVEncryptor.AUTH_BYTES; // reserve for one-time auth public static readonly int BufferSize = RecvSize + RecvReserveSize + 32; - // public Encryptor encryptor; - public IEncryptor encryptor; - public Server server; - // Client socket. - private AsyncSession _currentRemoteSession; + public DateTime lastActivity; - public Socket connection; - public ShadowsocksController controller; - public TCPRelay tcprelay; + private ShadowsocksController _controller; + private Configuration _config; + private TCPRelay _tcprelay; + private Socket _connection; - public DateTime lastActivity; + private IEncryptor _encryptor; + private Server _server; - private const int MaxRetry = 4; - private int _retryCount = 0; - private bool _proxyConnected; - private bool _destConnected; + private AsyncSession _currentRemoteSession; + + private const int MaxRetry = 4; + private int _retryCount = 0; + private bool _proxyConnected; + private bool _destConnected; - private byte _command; - private byte[] _firstPacket; - private int _firstPacketLength; + private byte _command; + private byte[] _firstPacket; + private int _firstPacketLength; - private int _totalRead = 0; - private int _totalWrite = 0; + private int _totalRead = 0; + private int _totalWrite = 0; - private byte[] _remoteRecvBuffer = new byte[BufferSize]; - private byte[] _remoteSendBuffer = new byte[BufferSize]; - private byte[] _connetionRecvBuffer = new byte[BufferSize]; - private byte[] _connetionSendBuffer = new byte[BufferSize]; + private byte[] _remoteRecvBuffer = new byte[BufferSize]; + private byte[] _remoteSendBuffer = new byte[BufferSize]; + private byte[] _connetionRecvBuffer = new byte[BufferSize]; + private byte[] _connetionSendBuffer = new byte[BufferSize]; - private bool _connectionShutdown = false; - private bool _remoteShutdown = false; - private bool _closed = false; + private bool _connectionShutdown = false; + private bool _remoteShutdown = false; + private bool _closed = false; - private object _encryptionLock = new object(); - private object _decryptionLock = new object(); + private object _encryptionLock = new object(); + private object _decryptionLock = new object(); private DateTime _startConnectTime; private DateTime _startReceivingTime; private DateTime _startSendingTime; - private int _bytesToSend; - private TCPRelay _tcprelay; // TODO: is _tcprelay equals tcprelay declared above? - private Configuration _config; - public TCPHandler(TCPRelay tcprelay, Configuration config) + public TCPHandler(ShadowsocksController controller, Configuration config, TCPRelay tcprelay, Socket socket) { - this._tcprelay = tcprelay; + this._controller = controller; this._config = config; + this._tcprelay = tcprelay; + this._connection = socket; } public void CreateRemote() { - Server server = controller.GetAServer(IStrategyCallerType.TCP, (IPEndPoint)connection.RemoteEndPoint); + Server server = _controller.GetAServer(IStrategyCallerType.TCP, (IPEndPoint)_connection.RemoteEndPoint); if (server == null || server.server == "") throw new ArgumentException("No server configured"); lock (_encryptionLock) { lock (_decryptionLock) { - encryptor = EncryptorFactory.GetEncryptor(server.method, server.password, server.auth, false); + _encryptor = EncryptorFactory.GetEncryptor(server.method, server.password, server.auth, false); } } - this.server = server; + this._server = server; } public void Start(byte[] firstPacket, int length) @@ -202,18 +198,19 @@ namespace Shadowsocks.Controller public void Close() { - lock (tcprelay.Handlers) + lock (this) { - tcprelay.Handlers.Remove(this); - } - lock (this) { if (_closed) return; _closed = true; } + lock (_tcprelay.Handlers) + { + _tcprelay.Handlers.Remove(this); + } try { - connection?.Shutdown(SocketShutdown.Both); - connection?.Close(); + _connection?.Shutdown(SocketShutdown.Both); + _connection?.Close(); } catch (Exception e) { @@ -233,7 +230,7 @@ namespace Shadowsocks.Controller { lock (_decryptionLock) { - encryptor?.Dispose(); + _encryptor?.Dispose(); } } } @@ -253,7 +250,7 @@ namespace Shadowsocks.Controller response = new byte[] { 0, 91 }; Logging.Error("socks 5 protocol error"); } - connection?.BeginSend(response, 0, response.Length, SocketFlags.None, new AsyncCallback(HandshakeSendCallback), null); + _connection?.BeginSend(response, 0, response.Length, SocketFlags.None, new AsyncCallback(HandshakeSendCallback), null); } else Close(); @@ -270,7 +267,7 @@ namespace Shadowsocks.Controller if (_closed) return; try { - connection.EndSend(ar); + _connection.EndSend(ar); // +-----+-----+-------+------+----------+----------+ // | VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | @@ -279,7 +276,7 @@ namespace Shadowsocks.Controller // +-----+-----+-------+------+----------+----------+ // Skip first 3 bytes // TODO validate - connection.BeginReceive(_connetionRecvBuffer, 0, 3, SocketFlags.None, new AsyncCallback(handshakeReceive2Callback), null); + _connection.BeginReceive(_connetionRecvBuffer, 0, 3, SocketFlags.None, new AsyncCallback(handshakeReceive2Callback), null); } catch (Exception e) { @@ -293,14 +290,14 @@ namespace Shadowsocks.Controller if (_closed) return; try { - int bytesRead = connection.EndReceive(ar); + int bytesRead = _connection.EndReceive(ar); if (bytesRead >= 3) { _command = _connetionRecvBuffer[1]; if (_command == 1) { byte[] response = { 5, 0, 0, 1, 0, 0, 0, 0, 0, 0 }; - connection.BeginSend(response, 0, response.Length, SocketFlags.None, new AsyncCallback(ResponseCallback), null); + _connection.BeginSend(response, 0, response.Length, SocketFlags.None, new AsyncCallback(ResponseCallback), null); } else if (_command == 3) HandleUDPAssociate(); @@ -320,7 +317,7 @@ namespace Shadowsocks.Controller private void HandleUDPAssociate() { - IPEndPoint endPoint = (IPEndPoint)connection.LocalEndPoint; + IPEndPoint endPoint = (IPEndPoint)_connection.LocalEndPoint; byte[] address = endPoint.Address.GetAddressBytes(); int port = endPoint.Port; byte[] response = new byte[4 + address.Length + 2]; @@ -337,7 +334,7 @@ namespace Shadowsocks.Controller address.CopyTo(response, 4); response[response.Length - 1] = (byte)(port & 0xFF); response[response.Length - 2] = (byte)((port >> 8) & 0xFF); - connection.BeginSend(response, 0, response.Length, SocketFlags.None, new AsyncCallback(ReadAll), true); + _connection.BeginSend(response, 0, response.Length, SocketFlags.None, new AsyncCallback(ReadAll), true); } private void ReadAll(IAsyncResult ar) @@ -347,15 +344,15 @@ namespace Shadowsocks.Controller { if (ar.AsyncState != null) { - connection.EndSend(ar); - connection.BeginReceive(_connetionRecvBuffer, 0, RecvSize, SocketFlags.None, new AsyncCallback(ReadAll), null); + _connection.EndSend(ar); + _connection.BeginReceive(_connetionRecvBuffer, 0, RecvSize, SocketFlags.None, new AsyncCallback(ReadAll), null); } else { - int bytesRead = connection.EndReceive(ar); + int bytesRead = _connection.EndReceive(ar); if (bytesRead > 0) { - connection.BeginReceive(_connetionRecvBuffer, 0, RecvSize, SocketFlags.None, new AsyncCallback(ReadAll), null); + _connection.BeginReceive(_connetionRecvBuffer, 0, RecvSize, SocketFlags.None, new AsyncCallback(ReadAll), null); } else Close(); @@ -372,7 +369,7 @@ namespace Shadowsocks.Controller { try { - connection?.EndSend(ar); + _connection?.EndSend(ar); StartConnect(); } catch (Exception e) @@ -432,8 +429,8 @@ namespace Shadowsocks.Controller proxyTimer.Enabled = true; proxyTimer.Session = session; - proxyTimer.DestEndPoint = SocketUtil.GetEndPoint(server.server, server.server_port); - proxyTimer.Server = server; + proxyTimer.DestEndPoint = SocketUtil.GetEndPoint(_server.server, _server.server_port); + proxyTimer.Server = _server; _proxyConnected = false; @@ -534,7 +531,7 @@ namespace Shadowsocks.Controller var session = timer.Session; Server server = timer.Server; - IStrategy strategy = controller.GetCurrentStrategy(); + IStrategy strategy = _controller.GetCurrentStrategy(); strategy?.SetFailure(server); Logging.Info($"{server.FriendlyName()} timed out"); session.Remote.Close(); @@ -560,7 +557,7 @@ namespace Shadowsocks.Controller { var session = (AsyncSession) ar.AsyncState; ServerTimer timer = session.State; - server = timer.Server; + _server = timer.Server; timer.Elapsed -= destConnectTimer_Elapsed; timer.Enabled = false; timer.Dispose(); @@ -573,13 +570,13 @@ namespace Shadowsocks.Controller if (_config.isVerboseLogging) { - Logging.Info($"Socket connected to ss server: {server.FriendlyName()}"); + Logging.Info($"Socket connected to ss server: {_server.FriendlyName()}"); } var latency = DateTime.Now - _startConnectTime; - IStrategy strategy = controller.GetCurrentStrategy(); - strategy?.UpdateLatency(server, latency); - _tcprelay.UpdateLatency(server, latency); + IStrategy strategy = _controller.GetCurrentStrategy(); + strategy?.UpdateLatency(_server, latency); + _tcprelay.UpdateLatency(_server, latency); StartPipe(session); } @@ -588,10 +585,10 @@ namespace Shadowsocks.Controller } catch (Exception e) { - if (server != null) + if (_server != null) { - IStrategy strategy = controller.GetCurrentStrategy(); - strategy?.SetFailure(server); + IStrategy strategy = _controller.GetCurrentStrategy(); + strategy?.SetFailure(_server); } Logging.LogUsefulException(e); RetryConnect(); @@ -605,7 +602,7 @@ namespace Shadowsocks.Controller { _startReceivingTime = DateTime.Now; session.Remote.BeginReceive(_remoteRecvBuffer, 0, RecvSize, SocketFlags.None, new AsyncCallback(PipeRemoteReceiveCallback), session); - connection?.BeginReceive(_connetionRecvBuffer, 0, RecvSize, SocketFlags.None, new AsyncCallback(PipeConnectionReceiveCallback), + _connection?.BeginReceive(_connetionRecvBuffer, 0, RecvSize, SocketFlags.None, new AsyncCallback(PipeConnectionReceiveCallback), new AsyncSession(session, true) /* to tell the callback this is the first time reading packet, and we haven't found the header yet. */); } catch (Exception e) @@ -623,7 +620,7 @@ namespace Shadowsocks.Controller var session = (AsyncSession) ar.AsyncState; int bytesRead = session.Remote.EndReceive(ar); _totalRead += bytesRead; - _tcprelay.UpdateInboundCounter(server, bytesRead); + _tcprelay.UpdateInboundCounter(_server, bytesRead); if (bytesRead > 0) { lastActivity = DateTime.Now; @@ -631,15 +628,15 @@ namespace Shadowsocks.Controller lock (_decryptionLock) { if (_closed) return; - encryptor.Decrypt(_remoteRecvBuffer, bytesRead, _remoteSendBuffer, out bytesToSend); + _encryptor.Decrypt(_remoteRecvBuffer, bytesRead, _remoteSendBuffer, out bytesToSend); } - connection.BeginSend(_remoteSendBuffer, 0, bytesToSend, SocketFlags.None, new AsyncCallback(PipeConnectionSendCallback), session); - IStrategy strategy = controller.GetCurrentStrategy(); - strategy?.UpdateLastRead(server); + _connection.BeginSend(_remoteSendBuffer, 0, bytesToSend, SocketFlags.None, new AsyncCallback(PipeConnectionSendCallback), session); + IStrategy strategy = _controller.GetCurrentStrategy(); + strategy?.UpdateLastRead(_server); } else { - connection.Shutdown(SocketShutdown.Send); + _connection.Shutdown(SocketShutdown.Send); _connectionShutdown = true; CheckClose(); } @@ -656,8 +653,8 @@ namespace Shadowsocks.Controller if (_closed) return; try { - if(connection == null) return; - int bytesRead = connection.EndReceive(ar); + if(_connection == null) return; + int bytesRead = _connection.EndReceive(ar); _totalWrite += bytesRead; var session = (AsyncSession) ar.AsyncState; @@ -705,14 +702,13 @@ namespace Shadowsocks.Controller lock (_encryptionLock) { if (_closed) return; - encryptor.Encrypt(_connetionRecvBuffer, bytesRead, _connetionSendBuffer, out bytesToSend); + _encryptor.Encrypt(_connetionRecvBuffer, bytesRead, _connetionSendBuffer, out bytesToSend); } - _tcprelay.UpdateOutboundCounter(server, bytesToSend); + _tcprelay.UpdateOutboundCounter(_server, bytesToSend); _startSendingTime = DateTime.Now; - _bytesToSend = bytesToSend; remote.BeginSend(_connetionSendBuffer, 0, bytesToSend, SocketFlags.None, new AsyncCallback(PipeRemoteSendCallback), session); - IStrategy strategy = controller.GetCurrentStrategy(); - strategy?.UpdateLastWrite(server); + IStrategy strategy = _controller.GetCurrentStrategy(); + strategy?.UpdateLastWrite(_server); } else { @@ -735,7 +731,7 @@ namespace Shadowsocks.Controller { var session = (AsyncSession)ar.AsyncState; session.Remote.EndSend(ar); - connection?.BeginReceive(_connetionRecvBuffer, 0, RecvSize, SocketFlags.None, new AsyncCallback(PipeConnectionReceiveCallback), session); + _connection?.BeginReceive(_connetionRecvBuffer, 0, RecvSize, SocketFlags.None, new AsyncCallback(PipeConnectionReceiveCallback), session); } catch (Exception e) { @@ -750,7 +746,7 @@ namespace Shadowsocks.Controller try { var session = (AsyncSession)ar.AsyncState; - connection?.EndSend(ar); + _connection?.EndSend(ar); session.Remote.BeginReceive(_remoteRecvBuffer, 0, RecvSize, SocketFlags.None, new AsyncCallback(PipeRemoteReceiveCallback), session); } catch (Exception e)