private void ConnectCallback(IAsyncResult ar)
        {
            if (_closed)
            {
                return;
            }
            try
            {
                var         session = (AsyncSession <ServerTimer>)ar.AsyncState;
                ServerTimer timer   = session.State;
                _server        = timer.Server;
                timer.Elapsed -= destConnectTimer_Elapsed;
                timer.Enabled  = false;
                timer.Dispose();

                var remote = session.Remote;
                // Complete the connection.
                remote.EndConnectDest(ar);

                _destConnected = true;

                if (_config.isVerboseLogging)
                {
                    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);

                StartPipe(session);
            }
            catch (ArgumentException)
            {
            }
            catch (Exception e)
            {
                if (_server != null)
                {
                    IStrategy strategy = _controller.GetCurrentStrategy();
                    strategy?.SetFailure(_server);
                }
                Logging.LogUsefulException(e);
                Close();
            }
        }
Beispiel #2
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);
                DoEncrypt(_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);
                    DoEncrypt(_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);

                _startConnectTime = DateTime.Now;
                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()}");
                }

                var latency = DateTime.Now - _startConnectTime;
                _controller.GetCurrentStrategy()?.UpdateLatency(_server, latency);
                _tcprelay.UpdateLatency(_server, latency);

                _startReceivingTime = DateTime.Now;

                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;
            }
        }