private async Task AcceptNewClientAsync( TcpClient client, ConnectionSetting connectionSettings, CancellationToken cancellationToken) { ILifetimeScope newScope = _scope.BeginLifetimeScope( ConnectionScopeTag, builder => { builder.RegisterInstance( new ConnectionInformation( client.Client.LocalEndPoint.ToString(), client.Client.RemoteEndPoint.ToString())); builder.RegisterInstance(new SecurableConnection(client.GetStream(), _keyProvider.GetKey(connectionSettings.Certificate))) .As <SecurableConnection>() .As <IConnectionSecurity>() .As <IVariableStreamReader>(); builder.RegisterInstance(connectionSettings); builder.Register(c => c.ResolveKeyed <IAuthenticationTransport>(connectionSettings.Protocol)) .As <IAuthenticationTransport>(); } ); var newSession = newScope.ResolveKeyed <IProtocolSession>(connectionSettings.Protocol); using (await SemaphoreLock.GetLockAsync(_sessionSemaphore, cancellationToken)) { _sessions.Add(new SessionHolder(newSession, newSession.RunAsync(cancellationToken), newScope)); } }
public async Task RunAsync(CancellationToken cancellationToken) { _log.Information($"Opening ports: {string.Join(",", _settings.Connections.Select(p => p.Port.ToString()))}"); TcpListener[] listeners = _settings.Connections .Select(p => new TcpListener(IPAddress.Any, p.Port)) .ToArray(); foreach (TcpListener l in listeners) { l.Start(); } Task <TcpClient>[] listenerTasks = listeners .Select(tcp => tcp.AcceptTcpClientAsync()) .ToArray(); while (!cancellationToken.IsCancellationRequested) { var tasks = new Task[listenerTasks.Length + _sessions.Count]; Array.Copy(listenerTasks, 0, tasks, 0, listenerTasks.Length); _sessions.Select(s => s.Task).ToList().CopyTo(tasks, listenerTasks.Length); int completedIndex = Task.WaitAny(tasks); Task task = tasks[completedIndex]; if (task is Task <TcpClient> tcpTask) { // This is a new connection task TcpClient client = tcpTask.Result; ConnectionSetting connectionSettings = _settings.Connections[completedIndex]; await AcceptNewClientAsync(client, connectionSettings, cancellationToken); // Wait for another connection listenerTasks[completedIndex] = listeners[completedIndex].AcceptTcpClientAsync(); } else { // One of the existing connections is closing using (await SemaphoreLock.GetLockAsync(_sessionSemaphore, cancellationToken)) { int sessionIndex = completedIndex - listenerTasks.Length; SessionHolder closingSession = _sessions[sessionIndex]; _log.Information($"Closing session {closingSession.Session.Id}..."); _sessions.RemoveAt(sessionIndex); closingSession.Scope.Dispose(); } } } foreach (TcpListener l in listeners) { l.Stop(); } }
public async Task Close(CancellationToken cancellationToken) { using (await SemaphoreLock.GetLockAsync(_sessionSemaphore, cancellationToken)) { Task[] closing = _sessions.Select(session => session.CloseAsync(cancellationToken)).ToArray(); Task.WaitAll(closing, cancellationToken); Task.WaitAll(_sessionLifetimes.ToArray(), cancellationToken); _sessions = null; _sessionLifetimes = null; } }
public async Task Close(CancellationToken cancellationToken) { using (await SemaphoreLock.GetLockAsync(_sessionSemaphore, cancellationToken)) { foreach (SessionHolder session in _sessions) { session.Scope.Dispose(); } await Task.WhenAll(_sessions.Select(s => s.Task)); _sessions = null; } }
public async Task Start(CancellationToken cancellationToken) { TcpListener[] listeners = _ports .Select(p => new TcpListener(IPAddress.Any, p)) .ToArray(); foreach (var l in listeners) { l.Start(); } Task <TcpClient>[] tasks = listeners.Select(tcp => tcp.AcceptTcpClientAsync()) .ToArray(); while (!cancellationToken.IsCancellationRequested) { int taskCompleted = Task.WaitAny(tasks); TcpClient client = tasks[taskCompleted].Result; using (await SemaphoreLock.GetLockAsync(_sessionSemaphore, cancellationToken)) { var securableConnection = new SecurableConnection(client.GetStream()); securableConnection.Certificate = ServerCertificate; var session = InitiateSession( securableConnection, client.Client.LocalEndPoint, client.Client.RemoteEndPoint); _sessions.Add(session); _sessionLifetimes.Add(session.Start(cancellationToken)); } // Wait for another connection tasks[taskCompleted] = listeners[taskCompleted].AcceptTcpClientAsync(); } foreach (var l in listeners) { l.Stop(); } }
public async Task SendMessageAsync(ImapMessage message, Encoding encoding, CancellationToken cancellationToken) { using (await SemaphoreLock.GetLockAsync(_sendSemaphore, cancellationToken)) { var builder = new StringBuilder(); builder.Append(message.Tag); foreach (IMessageData data in message.Data) { if (data is LiteralMessageData literal) { builder.Append("}"); builder.Append(literal.Length); builder.AppendLine("}"); await _connection.WriteAsync(builder.ToString(), encoding, cancellationToken); builder.Clear(); } else { if (builder.Length > 0) { builder.Append(" "); } builder.Append(data.ToMessageString()); } } if (builder.Length > 0) { _logger.Verbose("IMAP -> " + builder); builder.AppendLine(); await _connection.WriteAsync(builder.ToString(), encoding, cancellationToken); } } }