public void DisposeActiveSession() { lock (_locker) { if (_activeSession == null) { return; } _tokenSource?.Cancel(); _activeSession.SessionEnded -= OnSessionEnded; _activeSession.Disconnected -= OnSessionDisconnected; _activeSession.ReceiveAliveTimeoutOccured -= OnSessionReceiveAliveTimeout; _activeSession.ControlStateSetToError -= OnSessionControlStateSetToError; _activeSession.EventOccured -= OnSessionEventOccured; _activeSession.DisposeSession(); _logger.Info("Session with {0}:{1} ended, closed and disposed.", (object)_activeSession.RemoteEndPoint.Address, (object)_activeSession.RemoteEndPoint.Port); _activeSession = null; } }
public async Task <TLCFIClientSession> GetNewSession(IPEndPoint endPoint, TLCFIClientStateManager stateManager, CancellationToken token) { if (token.IsCancellationRequested) { return(null); } lock (_locker) { if (_activeSession != null && !_activeSession.Connected) { _logger.Warn("A session with {0}:{1} already exists, but is not connected. It will be disposed of.", _activeSession.RemoteEndPoint.Address, _activeSession.RemoteEndPoint.Port); DisposeActiveSession(); return(null); } if (_activeSession != null) { _logger.Warn("There already is a connected session with {0}:{1}. Simultaneous sessions are not allowed.", _activeSession.RemoteEndPoint.Address, _activeSession.RemoteEndPoint.Port); return(null); } } // Succesful registration interval if (DateTime.Now.Subtract(_lastSuccesfulRegister).TotalSeconds < 42) { var remaining = (int)(42 - DateTime.Now.Subtract(_lastSuccesfulRegister).TotalSeconds) + 1; _logger.Info("Need 42 seconds between succesful register calls. Still need to wait {0} seconds. ", remaining); await Task.Run(async() => { while (remaining > 0) { await Task.Delay(1000, token); remaining--; if (remaining > 0) { _logger.Trace("Starting new session in {0} seconds.", remaining); } } }, token); } _tokenSource = new CancellationTokenSource(); var session = new TLCFIClientSession(stateManager, endPoint, _tokenSource.Token); _activeSession = session; session.SessionEnded += OnSessionEnded; session.Disconnected += OnSessionDisconnected; session.ControlStateSetToError += OnSessionControlStateSetToError; session.ReceiveAliveTimeoutOccured += OnSessionReceiveAliveTimeout; session.EventOccured += OnSessionEventOccured; var watch = new Stopwatch(); watch.Reset(); var sesIp = endPoint.Address.ToString(); var sesPort = endPoint.Port.ToString(); while (!session.Connected) { try { var remaining = _timeout - watch.ElapsedMilliseconds; if (remaining > 0) { await Task.Delay((int)remaining, token); } _tries++; // Backoff procedure if (_tries >= 25) { _timeout = 60000; } else if (_tries >= 21) { _timeout = 30000; } else if (_tries >= 10) { _timeout = 5000; } else if (_tries >= 5) { _timeout = 2000; } watch.Reset(); watch.Start(); _logger.Info("Connecting to {0}:{1}, try {2}", sesIp, sesPort, _tries); ConnectingStarted?.Invoke(this, _tries); if (token.IsCancellationRequested || _tokenSource.IsCancellationRequested) { return(null); } await session.StartSessionAsync(_timeout); } catch (TaskCanceledException) { return(null); } catch { _logger.Warn("Connecting to {0}:{1} try {2} failed", sesIp, sesPort, _tries); ConnectingFailed?.Invoke(this, _tries); } } _logger.Info("TCP session with {0}:{1} started", sesIp, sesPort); TLCSessionStarted?.Invoke(this, session); return(session); }