示例#1
0
        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;
                }
            }
示例#3
0
 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);
         }
     }
 }
示例#4
0
        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();
                    }
                }
            }
        }
示例#5
0
        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;
            }
        }
示例#6
0
        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;
            }
        }
示例#7
0
        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);
            }
        }
示例#8
0
        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;
            }
        }
示例#9
0
        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;
            }
        }
示例#10
0
 /// <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);
     }
 }
示例#11
0
            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();
            }
        }
示例#12
0
        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;
            }
        }
示例#13
0
        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;
            }
        }
示例#14
0
            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;
                }
            }
示例#15
0
        // 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;
                }
            }
示例#17
0
        // 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;
            }
        }
示例#18
0
        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;
            }
        }
示例#19
0
        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;
            }
        }
示例#20
0
        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;
            }
        }
示例#21
0
            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;
                }
            }
示例#22
0
        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);
                }
            });
        }