private async Task ConsumeAsync(IServerChannel serverChannel) { try { // Establishes the session await serverChannel.EstablishSessionAsync( serverChannel.Transport.GetSupportedCompression().Intersect(_enabledCompressionOptions) .ToArray(), serverChannel.Transport.GetSupportedEncryption().Intersect(_enabledEncryptionOptions).ToArray(), _schemeOptions, _authenticator, _nodeRegistry.TryRegisterAsync, _listenerCts.Token) .ConfigureAwait(false); if (serverChannel.State == SessionState.Established) { await ListenAsync(serverChannel); } // If something bizarre occurs if (serverChannel.IsActive()) { await serverChannel.SendFailedSessionAsync( new Reason() { Code = ReasonCodes.SESSION_ERROR, Description = "The session was terminated by the server" }, _listenerCts.Token); } } catch (OperationCanceledException) when(_listenerCts.IsCancellationRequested) { if (serverChannel.IsActive()) { await serverChannel.SendFailedSessionAsync( new Reason() { Code = ReasonCodes.SESSION_ERROR, Description = "The server is being shut down" }, CancellationToken.None); } } catch (Exception ex) { if (_exceptionHandler != null) { await _exceptionHandler(ex).ConfigureAwait(false); } if (serverChannel.IsActive()) { await serverChannel.SendFailedSessionAsync( new Reason() { Code = ReasonCodes.SESSION_ERROR, Description = "An unexpected server error occurred" }, CancellationToken.None); } } finally { serverChannel.DisposeIfDisposable(); } }
static async Task ConsumeAsync(IServerChannel serverChannel, CancellationToken cancellationToken) { try { await serverChannel.EstablishSessionAsync( serverChannel.Transport.GetSupportedCompression(), serverChannel.Transport.GetSupportedEncryption(), new[] { AuthenticationScheme.Guest }, (identity, authentication) => new AuthenticationResult(null, new Node() { Name = EnvelopeId.NewId(), Domain = "limeprotocol.org", Instance = Environment.MachineName }).AsCompletedTask(), cancellationToken); if (serverChannel.State == SessionState.Established) { _nodeChannelsDictionary.Add(serverChannel.RemoteNode, serverChannel); // Consume the channel envelopes var consumeMessagesTask = ConsumeMessagesAsync(serverChannel, cancellationToken).WithPassiveCancellation(); var consumeCommandsTask = ConsumeCommandsAsync(serverChannel, cancellationToken).WithPassiveCancellation(); var consumeNotificationsTask = ConsumeNotificationsAsync(serverChannel, cancellationToken).WithPassiveCancellation(); // Awaits for the finishing envelope var finishingSessionTask = serverChannel.ReceiveFinishingSessionAsync(cancellationToken); // Stops the consumer when any of the tasks finishes await Task.WhenAny(finishingSessionTask, consumeMessagesTask, consumeCommandsTask, consumeNotificationsTask); if (finishingSessionTask.IsCompleted) { await serverChannel.SendFinishedSessionAsync(CancellationToken.None); } } if (serverChannel.State != SessionState.Finished && serverChannel.State != SessionState.Failed) { await serverChannel.SendFailedSessionAsync(new Reason() { Code = ReasonCodes.SESSION_ERROR, Description = "The session failed" }, CancellationToken.None); } } catch (OperationCanceledException) when(cancellationToken.IsCancellationRequested) { } finally { if (serverChannel.RemoteNode != null) { _nodeChannelsDictionary.Remove(serverChannel.RemoteNode); } serverChannel.DisposeIfDisposable(); } }
private async Task ConsumeAsync(IServerChannel serverChannel) { try { // Establishes the session await serverChannel.EstablishSessionAsync( serverChannel.Transport.GetSupportedCompression().Intersect(_enabledCompressionOptions) .ToArray(), serverChannel.Transport.GetSupportedEncryption().Intersect(_enabledEncryptionOptions).ToArray(), _schemeOptions, _authenticator, _listenerCts.Token) .ConfigureAwait(false); if (serverChannel.State == SessionState.Established) { if (!_nodeChannelsDictionary.TryAdd(serverChannel.RemoteNode, serverChannel)) { await serverChannel.SendFailedSessionAsync(new Reason() { Code = ReasonCodes.SESSION_ERROR, Description = "Could not register the channel node" }, _listenerCts.Token); return; } // Initializes a new consumer var channelListener = _channelListenerFactory(); try { // Consume the channel envelopes channelListener.Start(serverChannel); // Awaits for the finishing envelope var finishingSessionTask = serverChannel.ReceiveFinishingSessionAsync(_listenerCts.Token); // Stops the consumer when any of the tasks finishes await Task.WhenAny( finishingSessionTask, channelListener.MessageListenerTask, channelListener.CommandListenerTask, channelListener.NotificationListenerTask); if (finishingSessionTask.IsCompleted) { await serverChannel.SendFinishedSessionAsync(_listenerCts.Token); } } finally { channelListener.Stop(); if (serverChannel.RemoteNode != null) { _nodeChannelsDictionary.TryRemove(serverChannel.RemoteNode, out _); } } } // If something bizarre occurs if (serverChannel.State != SessionState.Finished && serverChannel.State != SessionState.Failed) { await serverChannel.SendFailedSessionAsync(new Reason() { Code = ReasonCodes.SESSION_ERROR, Description = "The session failed" }, _listenerCts.Token); } } catch (OperationCanceledException) when(_listenerCts.IsCancellationRequested) { await serverChannel.SendFailedSessionAsync(new Reason() { Code = ReasonCodes.SESSION_ERROR, Description = "The server is being shut down" }, CancellationToken.None); } catch (Exception ex) { if (_exceptionHandler != null) { await _exceptionHandler(ex).ConfigureAwait(false); } } finally { serverChannel.DisposeIfDisposable(); } }
private async Task EstablishSessionAsync(IServerChannel channel, CancellationToken cancellationToken) { try { cancellationToken.ThrowIfCancellationRequested(); _serverConnectedNodesDictionary.Add(channel.SessionId, channel); var timeoutToken = new CancellationTokenSource(TimeSpan.FromSeconds(60)); var newSession = await channel.ReceiveNewSessionAsync( CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutToken.Token).Token); timeoutToken = new CancellationTokenSource(TimeSpan.FromSeconds(60)); var negotiatedSession = await channel.NegotiateSessionAsync( channel.Transport.GetSupportedCompression(), channel.Transport.GetSupportedEncryption(), CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutToken.Token).Token); if (negotiatedSession.State == SessionState.Negotiating && negotiatedSession.Compression != null && negotiatedSession.Encryption != null) { await channel.SendNegotiatingSessionAsync( negotiatedSession.Compression.Value, negotiatedSession.Encryption.Value ); timeoutToken = new CancellationTokenSource(TimeSpan.FromSeconds(60)); if (channel.Transport.Compression != negotiatedSession.Compression.Value) { await channel.Transport.SetCompressionAsync( negotiatedSession.Compression.Value, CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutToken.Token).Token); } if (channel.Transport.Encryption != negotiatedSession.Encryption.Value) { await channel.Transport.SetEncryptionAsync( negotiatedSession.Encryption.Value, CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutToken.Token).Token); } timeoutToken = new CancellationTokenSource(TimeSpan.FromSeconds(60)); var authenticatedSession = await channel.AuthenticateSessionAsync( new AuthenticationScheme[] { AuthenticationScheme.Plain, AuthenticationScheme.Transport }, CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutToken.Token).Token); if (authenticatedSession.Authentication != null && authenticatedSession.From != null && authenticatedSession.From.Domain.Equals(_serverNode.Domain, StringComparison.OrdinalIgnoreCase)) { if (authenticatedSession.Authentication is PlainAuthentication) { var plainAuthentication = authenticatedSession.Authentication as PlainAuthentication; string password; if (_identityPasswordDictionary.TryGetValue(authenticatedSession.From.ToIdentity(), out password) && password.Equals(plainAuthentication.GetFromBase64Password())) { await RegisterChannel(channel, authenticatedSession.From, cancellationToken); } else { await channel.SendFailedSessionAsync( new Reason() { Code = ReasonCodes.SESSION_AUTHENTICATION_FAILED, Description = "Invalid username or password" }); } } else if (authenticatedSession.Authentication is TransportAuthentication) { var transportAuthentication = authenticatedSession.Authentication as PlainAuthentication; if (channel.Transport is IAuthenticatableTransport) { var authenticableTransport = channel.Transport as IAuthenticatableTransport; if (await authenticableTransport.AuthenticateAsync(authenticatedSession.From.ToIdentity()) != DomainRole.Unknown) { await RegisterChannel(channel, authenticatedSession.From, cancellationToken); } else { await channel.SendFailedSessionAsync( new Reason() { Code = ReasonCodes.SESSION_AUTHENTICATION_FAILED, Description = "The authentication failed" }); } } else { await channel.SendFailedSessionAsync( new Reason() { Code = ReasonCodes.SESSION_AUTHENTICATION_FAILED, Description = "The current transport doesn't support authentication" }); } } else { await channel.SendFailedSessionAsync( new Reason() { Code = ReasonCodes.SESSION_AUTHENTICATION_FAILED, Description = "Unsupported authenticaiton scheme" }); } } else { await channel.SendFailedSessionAsync( new Reason() { Code = ReasonCodes.SESSION_AUTHENTICATION_FAILED, Description = "Invalid user" }); } } else { await channel.SendFailedSessionAsync( new Reason() { Code = 1, Description = "Invalid selected negotiation options" }); } } finally { channel.DisposeIfDisposable(); } }
private async Task EstablishSessionAsync(IServerChannel channel, CancellationToken cancellationToken) { try { cancellationToken.ThrowIfCancellationRequested(); _serverConnectedNodesDictionary.Add(channel.SessionId, channel); var timeoutToken = new CancellationTokenSource(TimeSpan.FromSeconds(60)); var newSession = await channel.ReceiveNewSessionAsync( CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutToken.Token).Token); timeoutToken = new CancellationTokenSource(TimeSpan.FromSeconds(60)); var negotiatedSession = await channel.NegotiateSessionAsync( channel.Transport.GetSupportedCompression(), channel.Transport.GetSupportedEncryption(), CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutToken.Token).Token); if (negotiatedSession.State == SessionState.Negotiating && negotiatedSession.Compression != null && negotiatedSession.Encryption != null) { await channel.SendNegotiatingSessionAsync( negotiatedSession.Compression.Value, negotiatedSession.Encryption.Value ); timeoutToken = new CancellationTokenSource(TimeSpan.FromSeconds(60)); if (channel.Transport.Compression != negotiatedSession.Compression.Value) { await channel.Transport.SetCompressionAsync( negotiatedSession.Compression.Value, CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutToken.Token).Token); } if (channel.Transport.Encryption != negotiatedSession.Encryption.Value) { await channel.Transport.SetEncryptionAsync( negotiatedSession.Encryption.Value, CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutToken.Token).Token); } timeoutToken = new CancellationTokenSource(TimeSpan.FromSeconds(60)); var authenticatedSession = await channel.AuthenticateSessionAsync( new AuthenticationScheme[] { AuthenticationScheme.Plain, AuthenticationScheme.Transport }, CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutToken.Token).Token); if (authenticatedSession.Authentication != null && authenticatedSession.From != null && authenticatedSession.From.Domain.Equals(_serverNode.Domain, StringComparison.OrdinalIgnoreCase)) { if (authenticatedSession.Authentication is PlainAuthentication) { var plainAuthentication = authenticatedSession.Authentication as PlainAuthentication; string password; if (_identityPasswordDictionary.TryGetValue(authenticatedSession.From.ToIdentity(), out password) && password.Equals(plainAuthentication.GetFromBase64Password())) { await RegisterChannel(channel, authenticatedSession.From, cancellationToken); } else { await channel.SendFailedSessionAsync( new Reason() { Code = ReasonCodes.SESSION_AUTHENTICATION_FAILED, Description = "Invalid username or password" }); } } else if (authenticatedSession.Authentication is TransportAuthentication) { var transportAuthentication = authenticatedSession.Authentication as PlainAuthentication; if (channel.Transport is IAuthenticatableTransport) { var authenticableTransport = channel.Transport as IAuthenticatableTransport; if (await authenticableTransport.AuthenticateAsync(authenticatedSession.From.ToIdentity()) != DomainRole.Unknown) { await RegisterChannel(channel, authenticatedSession.From, cancellationToken); } else { await channel.SendFailedSessionAsync( new Reason() { Code = ReasonCodes.SESSION_AUTHENTICATION_FAILED, Description = "The authentication failed" }); } } else { await channel.SendFailedSessionAsync( new Reason() { Code = ReasonCodes.SESSION_AUTHENTICATION_FAILED, Description = "The current transport doesn't support authentication" }); } } else { await channel.SendFailedSessionAsync( new Reason() { Code = ReasonCodes.SESSION_AUTHENTICATION_FAILED, Description = "Unsupported authenticaiton scheme" }); } } else { await channel.SendFailedSessionAsync( new Reason() { Code = ReasonCodes.SESSION_AUTHENTICATION_FAILED, Description = "Invalid user" }); } } else { await channel.SendFailedSessionAsync( new Reason() { Code = 1, Description = "Invalid selected negotiation options" }); } } finally { channel.DisposeIfDisposable(); } }