private void Initialize() { _bufferManager = new GrowingByteBufferManager(_configuration.InitialPooledBufferCount, _configuration.ReceiveBufferSize); _saeaPool = new SaeaPool(1024, int.MaxValue, () => { var saea = new SaeaAwaitable(); return(saea); }, (saea) => { try { saea.Saea.AcceptSocket = null; saea.Saea.SetBuffer(EmptyArray, 0, 0); saea.Saea.RemoteEndPoint = null; saea.Saea.SocketFlags = SocketFlags.None; } catch (Exception ex) { // _log.Error(ex.Message, ex); } }); }
private async Task StartConnect(int port) { SaeaAwaitable tcpSaea = null; try { tcpSaea = _argsPool.Rent(); var realSaea = tcpSaea.Saea; realSaea.RemoteEndPoint = SocketUtil.GetEndPoint("127.0.0.1", port); tcpSaea.PrepareSAEABuffer(_firstPacket, _firstPacketLength); var ret = await _remote.ConnectAsync(tcpSaea); if (ret != SocketError.Success) { Close(); return; } Task.Factory.StartNew(StartPipe, TaskCreationOptions.PreferFairness).Forget(); } catch (Exception e) { Logging.LogUsefulException(e); Close(); } finally { _argsPool.Return(tcpSaea); tcpSaea = null; } }
private void ClearBuffer(SaeaAwaitable e) { if (e == null) { throw new ArgumentNullException(nameof(e)); } if (!_config._isSetBuffer) { return; } lock (_bufMgrLock) { try { if (_config._isSetBuffer) { byte[] buf = e.Saea.Buffer; e.Saea.SetBuffer(null, 0, 0); _bufferManager.ReturnBuffer(buf); } } catch (Exception exception) { Logging.LogUsefulException(exception); } } }
private void Dispose(bool disposing) { lock (_disposeLock) { if (_disposed) { return; } _disposed = true; } ReleaseUnmanagedResources(); if (disposing) { _argsPool.CompleteAdding(); while (_argsPool.Count > 0) { SaeaAwaitable arg = _argsPool.Take(); ClearBuffer(arg); arg.Dispose(); } _argsPool.Dispose(); lock (_bufMgrLock) { if (_config._isSetBuffer) { _bufferManager.Clear(); } } } }
private async Task RecvFirstPacket(Socket clientSocket) { SaeaAwaitable arg = null; try { arg = _argsPool.Rent(); var token = await clientSocket.FullReceiveTaskAsync(arg, MaxFirstPacketLen); var err = token.SocketError; ServiceUserToken serviceToken = null; var bytesReceived = token.BytesTotalTransferred; Logging.Debug($"RecvFirstPacket: {err},{bytesReceived}"); if (err == SocketError.Success && bytesReceived > 0) { serviceToken = new ServiceUserToken { socket = clientSocket, firstPacket = new byte[bytesReceived], firstPacketLength = bytesReceived }; Buffer.BlockCopy(arg.Saea.Buffer, 0, serviceToken.firstPacket, 0, bytesReceived); } else { Logging.Error($"RecvFirstPacket socket err: {err},{bytesReceived}"); goto Shutdown; } _argsPool.Return(arg); arg = null; foreach (IService service in _services) { if (service.Handle(serviceToken)) { return; } } Shutdown: // no service found for this if (clientSocket.ProtocolType == ProtocolType.Tcp) { clientSocket.Close(); } } catch (Exception e) { Logging.Error(e); } finally { _argsPool.Return(arg); arg = null; } }
private async Task HandshakeSendResponse() { SaeaAwaitable tcpSaea = null; try { if (_firstPacketLength <= 1) { Logging.Debug("Invalid first packet length"); Close(); return; } byte[] response = TCPRelay.Sock5HandshakeResponseSuccess; if (_firstPacket[0] != 5) { // reject socks 4 response = TCPRelay.Sock5HandshakeResponseReject; Logging.Error("socks 5 protocol error"); } tcpSaea = _argsPool.Rent(); tcpSaea.PrepareSAEABuffer(response, response.Length); var token = await _localSocket.FullSendTaskAsync(tcpSaea, response.Length); var err = token.SocketError; var bytesSent = token.BytesTotalTransferred; Logging.Debug($"HandshakeSendResponse: {err},{bytesSent}"); if (err != SocketError.Success) { Close(); return; } _argsPool.Return(tcpSaea); tcpSaea = null; Debug.Assert(bytesSent == response.Length); Task.Factory.StartNew(async() => { await Sock5RequestRecv(); }).Forget(); } catch (Exception e) { Logging.LogUsefulException(e); Close(); } finally { _argsPool.Return(tcpSaea); tcpSaea = null; } }
protected SaeaAwaitable CreateSaeaAwaitable() { lock (_bufMgrLock) { SaeaAwaitable args = new SaeaAwaitable(); if (_config._isSetBuffer) { byte[] buf = _bufferManager.TakeBuffer(_config._maxSingleBufSize); args.SetInitBufferSize(buf.Length); args.Saea.SetBuffer(buf, 0, buf.Length); } return(args); } }
private async Task StartRecvFrom() { SaeaAwaitable udpSaea = null; try { while (IsListening) { udpSaea = _argsPool.Rent(); udpSaea.Saea.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0); var err = await _udpSocket.ReceiveFromAsync(udpSaea); var saea = udpSaea.Saea; var bytesRecved = saea.BytesTransferred; if (err == SocketError.Success && bytesRecved > 0) { ServiceUserToken token = new ServiceUserToken { socket = _udpSocket, firstPacket = new byte[bytesRecved], firstPacketLength = bytesRecved, remoteEndPoint = saea.RemoteEndPoint }; Buffer.BlockCopy(saea.Buffer, 0, token.firstPacket, 0, bytesRecved); Task.Factory.StartNew(() => HandleUDPServices(token)).Forget(); } else { Logging.Error($"RecvFrom: {err},{bytesRecved}"); } _argsPool.Return(udpSaea); udpSaea = null; } } catch (Exception e) { Logging.LogUsefulException(e); } finally { _argsPool.Return(udpSaea); udpSaea = null; } }
private async Task StartRecvFrom() { SaeaAwaitable udpSaea = null; try { while (IsListening) { udpSaea = _argsPool.Rent(); udpSaea.Saea.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0); var err = await _udpSocket.ReceiveFromAsync(udpSaea); ServiceUserToken token = new ServiceUserToken(); if (err == SocketError.Success && udpSaea.Saea.BytesTransferred > 0) { var e = udpSaea.Saea; token.socket = _udpSocket; token.firstPacket = new byte[e.BytesTransferred]; token.firstPacketLength = e.BytesTransferred; token.remoteEndPoint = e.RemoteEndPoint; Buffer.BlockCopy(e.Buffer, e.Offset, token.firstPacket, 0, e.BytesTransferred); } _argsPool.Return(udpSaea); udpSaea = null; foreach (IService service in _services) { if (service.Handle(token)) { return; } } } } catch (Exception e) { Logging.LogUsefulException(e); } finally { _argsPool.Return(udpSaea); udpSaea = null; } }
/// <summary> /// Return a SAEA that rented before /// </summary> /// <param name="args"></param> public void Return(SaeaAwaitable args) { if (args == null) { return; } try { lock (_bufMgrLock) { args.ClearAndResetSaeaProperties(); if (!_argsPool.IsAddingCompleted) { _argsPool.Add(args); } } } catch (ObjectDisposedException e) { // In general, it doesn't make sense, log them in case we have interest Logging.LogUsefulException(e); } }
HTTP_CRLF; // End with an empty line public async Task SendResponse(byte[] firstPacket, int length, Socket socket, bool useSocks) { try { using (var saea = new SaeaAwaitable()) { string pac = GetPACContent(); IPEndPoint localEndPoint = (IPEndPoint)socket.LocalEndPoint; string proxy = GetPACAddress(firstPacket, length, localEndPoint, useSocks); pac = pac.Replace("__PROXY__", proxy); string text = string.Format(HTTP_OK_TEMPLATE, Encoding.UTF8.GetBytes(pac).Length) + pac; byte[] response = Encoding.UTF8.GetBytes(text); saea.Saea.SetBuffer(response, 0, response.Length); var ret = await socket.FullSendTaskAsync(saea, response.Length); var err = ret.SocketError; var bytesSent = ret.BytesTotalTransferred; if (err != SocketError.Success) { Logging.Error($"PAC send err: {err}"); socket.Close(); return; } Debug.Assert(bytesSent == response.Length); socket.Shutdown(SocketShutdown.Send); } } catch (Exception e) { Logging.LogUsefulException(e); socket.Close(); } }
private async Task Accept() { SaeaAwaitable saea = null; try { while (IsListening) { saea = _acceptArgsPool.Rent(); var socketError = await _tcpListenerSocket.AcceptAsync(saea); if (socketError == SocketError.Success) { Logging.Debug("accepted a connection"); var acceptedSocket = saea.Saea.AcceptSocket; Task.Factory.StartNew(async() => { await RecvFirstPacket(acceptedSocket); }, TaskCreationOptions.PreferFairness).Forget(); } else { Logging.Error($"Accept socket err: {socketError}"); } _acceptArgsPool.Return(saea); saea = null; } } catch (Exception ex) { Logging.LogUsefulException(ex); } finally { _acceptArgsPool.Return(saea); saea = null; } }
private async Task Sock5ConnectResponseSend() { SaeaAwaitable tcpSaea = null; try { tcpSaea = _argsPool.Rent(); tcpSaea.PrepareSAEABuffer(TCPRelay.Sock5ConnectRequestReplySuccess, TCPRelay.Sock5ConnectRequestReplySuccess.Length); var token = await _localSocket.FullSendTaskAsync(tcpSaea, TCPRelay.Sock5ConnectRequestReplySuccess.Length); var err = token.SocketError; var bytesSent = token.BytesTotalTransferred; Logging.Debug($"Sock5ConnectResponseSend: {err},{bytesSent}"); if (err != SocketError.Success) { Close(); return; } _argsPool.Return(tcpSaea); tcpSaea = null; Debug.Assert(bytesSent == TCPRelay.Sock5ConnectRequestReplySuccess.Length); Task.Factory.StartNew(async() => { await StartConnect(); }).Forget(); } catch (Exception e) { Logging.LogUsefulException(e); Close(); } finally { _argsPool.Return(tcpSaea); tcpSaea = null; } }
public async Task Start(byte[] data, int length) { Interlocked.Exchange(ref _state, _running); SaeaAwaitable upSaea = null; SaeaAwaitable downSaea = null; try { Logging.Debug($"-----UDP relay got {length}-----"); IEncryptor encryptor = EncryptorFactory.GetEncryptor(_server.method, _server.password); byte[] dataIn = new byte[length - 3]; Array.Copy(data, 3, dataIn, 0, length - 3); upSaea = _argsPool.Rent(); int outlen; encryptor.EncryptUDP(dataIn, dataIn.Length, upSaea.Saea.Buffer, out outlen); upSaea.Saea.SetBuffer(0, outlen); upSaea.Saea.RemoteEndPoint = _serverEndPoint; var ret = await _serverSocket.SendToAsync(upSaea); if (ret != SocketError.Success) { Logging.Error($"[udp] remote sendto {ret},{upSaea.Saea.BytesTransferred}"); Close(); return; } Logging.Debug($"[udp] remote sendto {_localEndPoint} -> {_serverEndPoint} {upSaea.Saea.BytesTransferred}"); _argsPool.Return(upSaea); upSaea = null; while (IsRunning) { downSaea = _argsPool.Rent(); downSaea.Saea.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0); ret = await _serverSocket.ReceiveFromAsync(downSaea); var bytesReceived = downSaea.Saea.BytesTransferred; if (ret != SocketError.Success) { Logging.Error($"[udp] remote recvfrom {ret},{bytesReceived}"); Close(); return; } Logging.Debug($"[udp] remote recvfrom {downSaea.Saea.RemoteEndPoint} -> {_localSocket.LocalEndPoint} {bytesReceived}"); byte[] dataOut = new byte[bytesReceived]; encryptor = EncryptorFactory.GetEncryptor(_server.method, _server.password); encryptor.DecryptUDP(downSaea.Saea.Buffer, bytesReceived, dataOut, out outlen); downSaea.ClearAndResetSaeaProperties(); byte[] buf = downSaea.Saea.Buffer; buf[0] = buf[1] = buf[2] = 0; Array.Copy(dataOut, 0, buf, 3, outlen); downSaea.Saea.RemoteEndPoint = _localEndPoint; downSaea.Saea.SetBuffer(0, outlen + 3); ret = await _localSocket.SendToAsync(downSaea); if (ret != SocketError.Success) { Logging.Error($"[udp] local sendto {ret},{downSaea.Saea.BytesTransferred}"); Close(); return; } Logging.Debug($"[udp] local sendto {_localSocket.LocalEndPoint} -> {_localEndPoint} {downSaea.Saea.BytesTransferred}"); _argsPool.Return(downSaea); downSaea = null; } } catch (Exception e) { Logging.LogUsefulException(e); Close(); } finally { _argsPool.Return(upSaea); upSaea = null; _argsPool.Return(downSaea); downSaea = null; } }
// server recv -> local send private async Task Downstream() { SaeaAwaitable serverRecvSaea = null; SaeaAwaitable localSendSaea = null; try { while (IsRunning) { serverRecvSaea = _argsPool.Rent(); var token = await _serverSocket.FullReceiveTaskAsync(serverRecvSaea, TCPRelay.RecvSize); var err = token.SocketError; var bytesRecved = token.BytesTotalTransferred; Logging.Debug($"Downstream server recv: {err},{bytesRecved}"); if (IsShutdown(token)) { //lock (_closeConnLock) //{ _localSocket.Shutdown(SocketShutdown.Send); _localShutdown = true; CheckClose(); //} return; } if (err != SocketError.Success) { Logging.Debug($"Downstream server recv socket err: {err}"); Close(); return; } Debug.Assert(bytesRecved <= TCPRelay.RecvSize); _tcprelay.UpdateInboundCounter(_server, bytesRecved); lastActivity = DateTime.Now; _controller.GetCurrentStrategy()?.UpdateLastRead(_server); localSendSaea = _argsPool.Rent(); int decBufLen = -1; lock (_decryptionLock) { DoDecrypt(serverRecvSaea.Saea.Buffer, bytesRecved, localSendSaea.Saea.Buffer, out decBufLen); } _argsPool.Return(serverRecvSaea); serverRecvSaea = null; token = await _localSocket.FullSendTaskAsync(localSendSaea, decBufLen); err = token.SocketError; var bytesSent = token.BytesTotalTransferred; Logging.Debug($"Downstream local send socket err: {err},{bytesSent}"); if (err != SocketError.Success) { Close(); return; } _argsPool.Return(localSendSaea); localSendSaea = null; Debug.Assert(bytesSent == decBufLen); } } catch (AggregateException agex) { foreach (var ex in agex.InnerExceptions) { Logging.LogUsefulException(ex); } Close(); } catch (Exception e) { Logging.LogUsefulException(e); Close(); } finally { _argsPool.Return(serverRecvSaea); serverRecvSaea = null; _argsPool.Return(localSendSaea); localSendSaea = null; } }
// local recv -> server send private async Task Upstream() { SaeaAwaitable localRecvSaea = null; SaeaAwaitable serverSendSaea = null; try { while (IsRunning) { localRecvSaea = _argsPool.Rent(); var token = await _local.FullReceiveTaskAsync(localRecvSaea, RecvSize); var err = token.SocketError; var bytesRecved = token.BytesTotalTransferred; Logging.Debug($"Upstream local recv: {err},{bytesRecved}"); if (err == SocketError.Success && bytesRecved <= 0) { _remote.Shutdown(SocketShutdown.Send); _remoteShutdown = true; CheckClose(); return; } if (err != SocketError.Success) { Logging.Debug($"Upstream local recv socket err: {err}"); Close(); return; } Debug.Assert(bytesRecved <= RecvSize); serverSendSaea = _argsPool.Rent(); Buffer.BlockCopy(localRecvSaea.Saea.Buffer, 0, serverSendSaea.Saea.Buffer, 0, bytesRecved); _argsPool.Return(localRecvSaea); localRecvSaea = null; token = await _remote.FullSendTaskAsync(serverSendSaea, bytesRecved); err = token.SocketError; var bytesSent = token.BytesTotalTransferred; Logging.Debug($"Upstream server send: {err},{bytesSent}"); if (err != SocketError.Success) { Close(); return; } _argsPool.Return(serverSendSaea); serverSendSaea = null; Debug.Assert(bytesSent == bytesRecved); } } catch (AggregateException agex) { foreach (var ex in agex.InnerExceptions) { Logging.LogUsefulException(ex); } Close(); } catch (Exception e) { Logging.LogUsefulException(e); Close(); } finally { _argsPool.Return(localRecvSaea); localRecvSaea = null; _argsPool.Return(serverSendSaea); serverSendSaea = null; } }
// local recv -> server send private async Task Upstream() { SaeaAwaitable localRecvSaea = null; SaeaAwaitable serverSendSaea = null; try { while (IsRunning) { localRecvSaea = _argsPool.Rent(); var token = await _localSocket.FullReceiveTaskAsync(localRecvSaea, TCPRelay.RecvSize); var err = token.SocketError; var bytesRecved = token.BytesTotalTransferred; Logging.Debug($"Upstream local recv: {err},{bytesRecved}"); if (err == SocketError.Success && bytesRecved <= 0) { _serverSocket.Shutdown(SocketShutdown.Send); _remoteShutdown = true; CheckClose(); return; } if (err != SocketError.Success) { Logging.Debug($"Upstream local recv socket err: {err}"); Close(); return; } Debug.Assert(bytesRecved <= TCPRelay.RecvSize); serverSendSaea = _argsPool.Rent(); int encBufLen = -1; lock (_encryptionLock) { _encryptor.Encrypt(localRecvSaea.Saea.Buffer, bytesRecved, serverSendSaea.Saea.Buffer, out encBufLen); } _argsPool.Return(localRecvSaea); localRecvSaea = null; _tcprelay.UpdateOutboundCounter(_server, encBufLen); token = await _serverSocket.FullSendTaskAsync(serverSendSaea, encBufLen); err = token.SocketError; var bytesSent = token.BytesTotalTransferred; Logging.Debug($"Upstream server send: {err},{bytesSent}"); if (err != SocketError.Success) { Close(); return; } _argsPool.Return(serverSendSaea); serverSendSaea = null; Debug.Assert(bytesSent == encBufLen); } } catch (AggregateException agex) { foreach (var ex in agex.InnerExceptions) { Logging.LogUsefulException(ex); } Close(); } catch (Exception e) { Logging.LogUsefulException(e); Close(); } finally { _argsPool.Return(localRecvSaea); localRecvSaea = null; _argsPool.Return(serverSendSaea); serverSendSaea = null; } }
private async Task StartConnect() { SaeaAwaitable serverSaea = null; try { CreateRemote(); _serverSocket = new Socket(SocketType.Stream, ProtocolType.Tcp); _serverSocket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); _serverSocket.SetTFO(); // encrypt and attach encrypted buffer to ConnectAsync serverSaea = _argsPool.Rent(); var realSaea = serverSaea.Saea; var encryptedbufLen = -1; Logging.Dump("StartConnect(): enc addrBuf", _addrBuf, _addrBufLength); lock (_encryptionLock) { _encryptor.Encrypt(_addrBuf, _addrBufLength, realSaea.Buffer, out encryptedbufLen); } Logging.Debug("StartConnect(): addrBuf enc len " + encryptedbufLen); if (_remainingBytesLen > 0) { Logging.Debug($"StartConnect(): remainingBytesLen: {_remainingBytesLen}"); var encRemainingBufLen = -1; byte[] tmp = new byte[4096]; Logging.Dump("StartConnect(): enc remaining", _remainingBytes, _remainingBytesLen); lock (_encryptionLock) { _encryptor.Encrypt(_remainingBytes, _remainingBytesLen, tmp, out encRemainingBufLen); } Logging.Debug("StartConnect(): remaining enc len " + encRemainingBufLen); Buffer.BlockCopy(tmp, 0, realSaea.Buffer, encryptedbufLen, encRemainingBufLen); encryptedbufLen += encRemainingBufLen; } Logging.Debug("actual enc buf len " + encryptedbufLen); realSaea.RemoteEndPoint = SocketUtil.GetEndPoint(_server.server, _server.server_port); realSaea.SetBuffer(0, encryptedbufLen); var err = await _serverSocket.ConnectAsync(serverSaea); if (err != SocketError.Success) { Logging.Error($"StartConnect: {err}"); Close(); return; } Logging.Debug("remote connected"); if (serverSaea.Saea.BytesTransferred != encryptedbufLen) { // not sent all data, it may caused by TFO, disable it Logging.Info("Disable TCP Fast Open due to initial send failure"); Program.DisableTFO(); Close(); return; } _argsPool.Return(serverSaea); serverSaea = null; if (_config.isVerboseLogging) { Logging.Info($"Socket connected to ss server: {_server.FriendlyName()}"); } Task.Factory.StartNew(StartPipe, TaskCreationOptions.PreferFairness).Forget(); } catch (AggregateException agex) { foreach (var ex in agex.InnerExceptions) { Logging.LogUsefulException(ex); } Close(); } catch (Exception e) { Logging.LogUsefulException(e); Close(); } finally { _argsPool.Return(serverSaea); serverSaea = null; } }
private async Task HandleUDPAssociate() { IPEndPoint endPoint = (IPEndPoint)_localSocket.LocalEndPoint; IPAddress endPointAddress = endPoint.Address; if (endPointAddress.IsIPv4MappedToIPv6) { endPointAddress = endPointAddress.MapToIPv4(); } byte[] address = endPointAddress.GetAddressBytes(); int port = endPoint.Port; byte[] response = new byte[4 + address.Length + ADDR_PORT_LEN]; response[0] = 5; switch (endPointAddress.AddressFamily) { case AddressFamily.InterNetwork: response[3] = ATYP_IPv4; break; case AddressFamily.InterNetworkV6: response[3] = ATYP_IPv6; break; } Array.Copy(address, 0, response, 4, address.Length); response[response.Length - 1] = (byte)(port & 0xFF); response[response.Length - 2] = (byte)((port >> 8) & 0xFF); SaeaAwaitable tcpSaea = null; SaeaAwaitable circularRecvSaea = null; try { tcpSaea = _argsPool.Rent(); tcpSaea.PrepareSAEABuffer(response, response.Length); var token = await _localSocket.FullSendTaskAsync(tcpSaea, response.Length); var err = token.SocketError; var sentSize = token.BytesTotalTransferred; Logging.Debug($"Udp assoc local send: {err},{sentSize}"); if (err != SocketError.Success) { Close(); return; } Debug.Assert(sentSize == response.Length); _argsPool.Return(tcpSaea); tcpSaea = null; circularRecvSaea = _argsPool.Rent(); while (IsRunning) { // UDP Assoc: Read all from socket and wait until client closes the connection token = await _localSocket.FullReceiveTaskAsync(circularRecvSaea, TCPRelay.RecvSize); Logging.Debug($"udp assoc local recv: {err}"); var ret = token.SocketError; var bytesRecved = token.BytesTotalTransferred; if (ret != SocketError.Success) { Logging.Error($"udp assoc: {ret},{bytesRecved}"); Close(); return; } if (bytesRecved <= 0) { Close(); return; } circularRecvSaea.ClearAndResetSaeaProperties(); } _argsPool.Return(circularRecvSaea); circularRecvSaea = null; } catch (Exception e) { Logging.LogUsefulException(e); Close(); } finally { _argsPool.Return(tcpSaea); tcpSaea = null; _argsPool.Return(circularRecvSaea); circularRecvSaea = null; } }
private async Task Sock5RequestRecv() { SaeaAwaitable tcpSaea = null; try { tcpSaea = _argsPool.Rent(); var token = await _localSocket.FullReceiveTaskAsync(tcpSaea, TCPRelay.RecvSize); var err = token.SocketError; var recvSize = token.BytesTotalTransferred; Logging.Debug($"Sock5RequestRecv: {err},{recvSize}"); if (err != SocketError.Success) { Close(); return; } var recvBuf = tcpSaea.Saea.Buffer; if (recvSize >= 5) { byte _command = recvBuf[1]; if (_command != TCPRelay.CMD_CONNECT && _command != TCPRelay.CMD_UDP_ASSOC) { Logging.Debug("Unsupported CMD=" + _command); Close(); return; } ParseAddrBuf(recvBuf, recvSize); /* drop [ VER | CMD | RSV ] */ var totalTransferredWithoutLeading = recvSize - 3; // save remaing _remainingBytesLen = totalTransferredWithoutLeading - _addrBufLength; if (_remainingBytesLen > 0) { _remainingBytes = new byte[_remainingBytesLen]; Buffer.BlockCopy(recvBuf, _addrBufLength, _remainingBytes, 0, _remainingBytesLen); } _argsPool.Return(tcpSaea); tcpSaea = null; // read address and call the corresponding method if (_command == TCPRelay.CMD_CONNECT) { Task.Factory.StartNew(async() => { await Sock5ConnectResponseSend(); }).Forget(); } else if (_command == TCPRelay.CMD_UDP_ASSOC) { Task.Factory.StartNew(async() => { await HandleUDPAssociate(); }).Forget(); } } } catch (Exception e) { Logging.LogUsefulException(e); Close(); } finally { _argsPool.Return(tcpSaea); tcpSaea = null; } }
public async Task Start(byte[] data, int length) { Interlocked.Exchange(ref _state, _running); SaeaAwaitable udpSaea = null; try { while (IsRunning) { IEncryptor encryptor = EncryptorFactory.GetEncryptor(_server.method, _server.password); byte[] dataIn = new byte[length - 3]; Array.Copy(data, 3, dataIn, 0, length - 3); udpSaea = _argsPool.Rent(); int outlen; encryptor.EncryptUDP(dataIn, length - 3, udpSaea.Saea.Buffer, out outlen); udpSaea.Saea.SetBuffer(0, outlen); udpSaea.Saea.RemoteEndPoint = _remoteEndPoint; Logging.Debug(_localEndPoint, _remoteEndPoint, outlen, "UDP Relay"); var ret = await _remote.SendToAsync(udpSaea); if (ret != SocketError.Success) { Close(); return; } udpSaea = _argsPool.Rent(); udpSaea.Saea.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0); ret = await _remote.ReceiveFromAsync(udpSaea); if (ret != SocketError.Success) { Close(); return; } var bytesReceived = udpSaea.Saea.BytesTransferred; Logging.Debug($"++++++Receive Server Port, size:" + bytesReceived); byte[] dataOut = new byte[bytesReceived]; encryptor = EncryptorFactory.GetEncryptor(_server.method, _server.password); encryptor.DecryptUDP(udpSaea.Saea.Buffer, bytesReceived, dataOut, out outlen); _argsPool.Return(udpSaea); udpSaea = null; udpSaea = _argsPool.Rent(); byte[] buf = udpSaea.Saea.Buffer; buf[0] = buf[1] = buf[2] = 0; Array.Copy(dataOut, 0, buf, 3, outlen); udpSaea.Saea.RemoteEndPoint = _localEndPoint; udpSaea.Saea.SetBuffer(0, outlen + 3); Logging.Debug(_localEndPoint, _remoteEndPoint, outlen, "UDP Relay"); ret = await _local.SendToAsync(udpSaea); if (ret != SocketError.Success) { Close(); return; } _argsPool.Return(udpSaea); udpSaea = null; } } catch (Exception e) { Logging.LogUsefulException(e); Close(); } finally { _argsPool.Return(udpSaea); udpSaea = null; } }
private void Initialize() { _bufferManager = new GrowingByteBufferManager(_configuration.InitialPooledBufferCount, _configuration.ReceiveBufferSize); _acceptSaeaPool = new SaeaPool(16, 32, () => { var saea = new SaeaAwaitable(); return(saea); }, (saea) => { try { saea.Saea.AcceptSocket = null; saea.Saea.SetBuffer(0, 0); saea.Saea.RemoteEndPoint = null; saea.Saea.SocketFlags = SocketFlags.None; } catch (Exception ex) { // _log.Error(ex.Message, ex); } }); _handleSaeaPool = new SaeaPool(1024, int.MaxValue, () => { var saea = new SaeaAwaitable(); return(saea); }, (saea) => { try { saea.Saea.AcceptSocket = null; saea.Saea.SetBuffer(EmptyArray, 0, 0); saea.Saea.RemoteEndPoint = null; saea.Saea.SocketFlags = SocketFlags.None; } catch (Exception ex) { // _log.Error(ex.Message, ex); } }); _sessionPool = new SessionPool(1024, int.MaxValue, () => { var session = new TcpSocketSaeaSession(_configuration, _bufferManager, _handleSaeaPool, _dispatcher, this); return(session); }, (session) => { try { session.Clear(); } catch (Exception ex) { // _log.Error(ex.Message, ex); } }); }