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