예제 #1
0
        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();
            }
        }
예제 #2
0
        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();
            }
        }
예제 #3
0
        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();
            }
        }
예제 #4
0
        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();
            }            
        }
예제 #5
0
        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();
            }
        }