Exemplo n.º 1
0
        public Tuple <INatsConnection, IList <IOp> > OpenConnection(ConnectionInfo connectionInfo, CancellationToken cancellationToken)
        {
            EnsureArg.IsNotNull(connectionInfo, nameof(connectionInfo));

            if (cancellationToken.IsCancellationRequested)
            {
                throw NatsException.CouldNotEstablishAnyConnection();
            }

            var hosts = new Queue <Host>(connectionInfo.Hosts.GetRandomized());

            while (!cancellationToken.IsCancellationRequested && hosts.Any())
            {
                var host = hosts.Dequeue();

                try
                {
                    return(EstablishConnection(
                               host,
                               connectionInfo,
                               cancellationToken));
                }
                catch (Exception ex)
                {
                    Logger.Error($"Error while connecting to {host}. Trying with next host (if any).", ex);
                }
            }

            throw NatsException.CouldNotEstablishAnyConnection();
        }
Exemplo n.º 2
0
 private void ThrowIfNotConnected()
 {
     if (!IsConnected)
     {
         throw NatsException.NotConnected();
     }
 }
Exemplo n.º 3
0
        public void Pub(string subject, ReadOnlyMemory <byte> body, string replyTo = null)
        {
            if (body.Length > _maxPayload)
            {
                throw NatsException.ExceededMaxPayload(_maxPayload, body.Length);
            }

            PubCmd.Write(_writer, subject, replyTo, body);
        }
Exemplo n.º 4
0
        public async Task WriteAsync(byte[] data)
        {
            if (data.Length > _maxPayloadSize)
            {
                throw NatsException.ExceededMaxPayload(_maxPayloadSize, data.Length);
            }

            await _stream.WriteAsync(data, 0, data.Length, _cancellationToken).ConfigureAwait(false);
        }
Exemplo n.º 5
0
        public void Write(byte[] data)
        {
            if (data.Length > _maxPayloadSize)
            {
                throw NatsException.ExceededMaxPayload(_maxPayloadSize, data.Length);
            }

            _stream.Write(data, 0, data.Length);
        }
Exemplo n.º 6
0
        public Task PubAsync(string subject, ReadOnlyMemory <byte> body, string replyTo = null)
        {
            if (body.Length > _maxPayload)
            {
                throw NatsException.ExceededMaxPayload(_maxPayload, body.Length);
            }

            return(PubCmd.WriteAsync(_writer, subject.AsMemory(), replyTo.AsMemory(), body));
        }
Exemplo n.º 7
0
        public void Pub(string subject, string body, string replyTo = null)
        {
            var payload = NatsEncoder.GetBytes(body);

            if (payload.Length > _maxPayload)
            {
                throw NatsException.ExceededMaxPayload(_maxPayload, payload.Length);
            }

            PubCmd.Write(_writer, subject, replyTo, payload);
        }
Exemplo n.º 8
0
        public Task PubAsync(string subject, string body, string replyTo = null)
        {
            var payload = NatsEncoder.GetBytes(body);

            if (payload.Length > _maxPayload)
            {
                throw NatsException.ExceededMaxPayload(_maxPayload, payload.Length);
            }

            return(PubCmd.WriteAsync(_writer, subject.AsMemory(), replyTo.AsMemory(), payload));
        }
Exemplo n.º 9
0
        public async Task WriteAsync(IPayload data)
        {
            if (data.Size > _maxPayloadSize)
            {
                throw NatsException.ExceededMaxPayload(_maxPayloadSize, data.Size);
            }

            for (var i = 0; i < data.BlockCount; i++)
            {
                await _stream.WriteAsync(data[i], 0, data[i].Length, _cancellationToken).ConfigureAwait(false);
            }
        }
Exemplo n.º 10
0
        public void Write(IPayload data)
        {
            if (data.Size > _maxPayloadSize)
            {
                throw NatsException.ExceededMaxPayload(_maxPayloadSize, data.Size);
            }

            for (var i = 0; i < data.BlockCount; i++)
            {
                _stream.Write(data[i], 0, data[i].Length);
            }
        }
Exemplo n.º 11
0
        private static NatsServerInfo VerifyConnection(Host host, ConnectionInfo connectionInfo, Socket socket, Func <IOp> readOne)
        {
            if (!socket.Connected)
            {
                throw NatsException.FailedToConnectToHost(host, "No connection could be established.");
            }

            var op = readOne();

            if (op == null)
            {
                throw NatsException.FailedToConnectToHost(host, "Expected to get INFO after establishing connection. Got nothing.");
            }

            var infoOp = op as InfoOp;

            if (infoOp == null)
            {
                throw NatsException.FailedToConnectToHost(host, $"Expected to get INFO after establishing connection. Got {op.GetType().Name}.");
            }

            Logger.Debug($"Got INFO during connect. {infoOp.GetAsString()}");

            var serverInfo  = NatsServerInfo.Parse(infoOp.Message);
            var credentials = host.HasNonEmptyCredentials() ? host.Credentials : connectionInfo.Credentials;

            if (serverInfo.AuthRequired && (credentials == null || credentials == Credentials.Empty))
            {
                throw NatsException.MissingCredentials(host);
            }

            socket.Send(ConnectCmd.Generate(connectionInfo.Verbose, credentials));
            socket.Send(PingCmd.Generate());

            op = readOne();
            if (op == null)
            {
                throw NatsException.FailedToConnectToHost(host, "Expected to read something after CONNECT and PING. Got nothing.");
            }

            if (op is ErrOp)
            {
                throw NatsException.FailedToConnectToHost(host, $"Expected to get PONG after sending CONNECT and PING. Got {op.GetAsString()}.");
            }

            if (!socket.Connected)
            {
                throw NatsException.FailedToConnectToHost(host, "No connection could be established.");
            }

            return(serverInfo);
        }
Exemplo n.º 12
0
        internal static void Connect(this Socket socket, Host host, int timeoutMs, CancellationToken cancellationToken)
        {
            var endPoint = new DnsEndPoint(host.Address, host.Port);

#if NET451
            var connectTask = Task.Factory.FromAsync(
                socket.BeginConnect(endPoint, null, null),
                _ => { });
#else
            var connectTask = socket.ConnectAsync(endPoint);
#endif

            if (connectTask.Wait(timeoutMs, cancellationToken))
            {
                return;
            }

            throw NatsException.FailedToConnectToHost(
                      host, $"Socket could not connect against {host}, within specified timeout {timeoutMs.ToString()}ms.");
        }
Exemplo n.º 13
0
        internal static async Task ConnectAsync(this Socket socket, Host host, int timeoutMs, CancellationToken cancellationToken)
        {
            var endPoint = new DnsEndPoint(host.Address, host.Port);

            var connectTask = socket.ConnectAsync(endPoint);

            await Task.WhenAny(Task.Delay(timeoutMs, cancellationToken), connectTask).ConfigureAwait(false);

            //var connectedOk = socket.Connected && connectTask.IsCompletedSuccessfully;
            //if (connectedOk)
            //    return;

            if (socket.Connected)
            {
                return;
            }

            socket.Close();

            throw NatsException.FailedToConnectToHost(
                      host, $"Socket could not connect against {host}, within specified timeout {timeoutMs.ToString()}ms.");
        }
Exemplo n.º 14
0
        public async Task <(INatsConnection connection, IList <IOp> consumedOps)> OpenConnectionAsync(
            ConnectionInfo connectionInfo,
            CancellationToken cancellationToken)
        {
            if (connectionInfo == null)
            {
                throw new ArgumentNullException(nameof(connectionInfo));
            }

            cancellationToken.ThrowIfCancellationRequested();

            var hosts = new Queue <Host>(connectionInfo.Hosts.GetRandomized()); //TODO: Rank

            bool ShouldTryAndConnect() => !cancellationToken.IsCancellationRequested && hosts.Any();

            while (ShouldTryAndConnect())
            {
                var host = hosts.Dequeue();

                try
                {
                    return(await EstablishConnectionAsync(
                               host,
                               connectionInfo,
                               cancellationToken).ConfigureAwait(false));
                }
                catch (Exception ex)
                {
                    Logger.Error($"Error while connecting to {host}. Trying with next host (if any).", ex);

                    if (!ShouldTryAndConnect())
                    {
                        throw;
                    }
                }
            }

            throw NatsException.CouldNotEstablishAnyConnection();
        }
Exemplo n.º 15
0
        private async Task <(INatsConnection connection, IList <IOp> consumedOps)> EstablishConnectionAsync(
            Host host,
            ConnectionInfo connectionInfo,
            CancellationToken cancellationToken)
        {
            var serverCertificateValidation = connectionInfo.ServerCertificateValidation ?? DefaultServerCertificateValidation;

            bool RemoteCertificateValidationCallback(object _, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
            => serverCertificateValidation(certificate, chain, errors);

            var    consumedOps = new List <IOp>();
            Socket socket      = null;
            Stream stream      = null;

            try
            {
                socket = _socketFactory.Create(connectionInfo.SocketOptions);
                await socket.ConnectAsync(
                    host,
                    connectionInfo.SocketOptions.ConnectTimeoutMs,
                    cancellationToken).ConfigureAwait(false);

                stream = socket.CreateReadWriteStream();
                var reader = new NatsOpStreamReader(stream);

                var op = reader.ReadOneOp();
                if (op == null)
                {
                    throw NatsException.FailedToConnectToHost(host,
                                                              "Expected to get INFO after establishing connection. Got nothing.");
                }

                if (!(op is InfoOp infoOp))
                {
                    throw NatsException.FailedToConnectToHost(host,
                                                              $"Expected to get INFO after establishing connection. Got {op.GetType().Name}.");
                }

                var serverInfo  = NatsServerInfo.Parse(infoOp.Message);
                var credentials = host.HasNonEmptyCredentials() ? host.Credentials : connectionInfo.Credentials;
                if (serverInfo.AuthRequired && (credentials == null || credentials == Credentials.Empty))
                {
                    throw NatsException.MissingCredentials(host);
                }

                if (serverInfo.TlsVerify && connectionInfo.ClientCertificates.Count == 0)
                {
                    throw NatsException.MissingClientCertificates(host);
                }

                consumedOps.Add(op);

                if (serverInfo.TlsRequired)
                {
                    await stream.DisposeAsync();

                    stream = new SslStream(socket.CreateReadWriteStream(), false, RemoteCertificateValidationCallback, null, EncryptionPolicy.RequireEncryption);
                    var ssl = (SslStream)stream;

                    var clientAuthOptions = new SslClientAuthenticationOptions
                    {
                        RemoteCertificateValidationCallback = RemoteCertificateValidationCallback,
                        AllowRenegotiation             = true,
                        CertificateRevocationCheckMode = X509RevocationMode.Online,
                        ClientCertificates             = connectionInfo.ClientCertificates,
                        EnabledSslProtocols            = SslProtocols.Tls12,
                        EncryptionPolicy = EncryptionPolicy.RequireEncryption,
                        TargetHost       = host.Address
                    };

                    await ssl.AuthenticateAsClientAsync(clientAuthOptions, cancellationToken).ConfigureAwait(false);

                    reader = new NatsOpStreamReader(ssl);
                }

                stream.Write(ConnectCmd.Generate(connectionInfo.Verbose, credentials, connectionInfo.Name));
                stream.Write(PingCmd.Bytes.Span);
                await stream.FlushAsync(cancellationToken).ConfigureAwait(false);

                op = reader.ReadOneOp();
                if (op == null)
                {
                    throw NatsException.FailedToConnectToHost(host,
                                                              "Expected to read something after CONNECT and PING. Got nothing.");
                }

                if (op is ErrOp)
                {
                    throw NatsException.FailedToConnectToHost(host,
                                                              $"Expected to get PONG after sending CONNECT and PING. Got {op.GetAsString()}.");
                }

                if (!socket.Connected)
                {
                    throw NatsException.FailedToConnectToHost(host, "No connection could be established.");
                }

                consumedOps.Add(op);

                return(
                    new NatsConnection(
                        serverInfo,
                        socket,
                        stream,
                        cancellationToken),
                    consumedOps);
            }
            catch
            {
                Swallow.Everything(
                    () =>
                {
                    stream?.Dispose();
                    stream = null;
                },
                    () =>
                {
                    if (socket == null)
                    {
                        return;
                    }

                    if (socket.Connected)
                    {
                        socket.Shutdown(SocketShutdown.Both);
                    }

                    socket.Dispose();
                    socket = null;
                });

                throw;
            }
        }