private async Task <RegistrationOperationStatus> RegisterDeviceAsync(
            AmqpClientConnection client,
            string correlationId,
            DeviceRegistration deviceRegistration)
        {
            AmqpMessage amqpMessage;

            if (deviceRegistration == null)
            {
                amqpMessage = AmqpMessage.Create(new MemoryStream(), true);
            }
            else
            {
                var customContentStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(deviceRegistration)));
                amqpMessage = AmqpMessage.Create(customContentStream, true);
            }
            amqpMessage.Properties.CorrelationId = correlationId;
            amqpMessage.ApplicationProperties.Map[MessageApplicationPropertyNames.OperationType] =
                DeviceOperations.Register;
            amqpMessage.ApplicationProperties.Map[MessageApplicationPropertyNames.ForceRegistration] = false;
            var outcome = await client.AmqpSession.SendingLink
                          .SendMessageAsync(amqpMessage, new ArraySegment <byte>(Guid.NewGuid().ToByteArray()),
                                            TimeoutConstant).ConfigureAwait(false);

            ValidateOutcome(outcome);
            var amqpResponse = await client.AmqpSession.ReceivingLink.ReceiveMessageAsync(TimeoutConstant)
                               .ConfigureAwait(false);

            client.AmqpSession.ReceivingLink.AcceptMessage(amqpResponse);
            string jsonResponse = await new StreamReader(amqpResponse.BodyStream).ReadToEndAsync()
                                  .ConfigureAwait(false);

            return(JsonConvert.DeserializeObject <RegistrationOperationStatus>(jsonResponse));
        }
        private async Task <RegistrationOperationStatus> OperationStatusLookupAsync(
            AmqpClientConnection client,
            string operationId,
            string correlationId)
        {
            var amqpMessage = AmqpMessage.Create(new AmqpValue()
            {
                Value = DeviceOperations.GetOperationStatus
            });

            amqpMessage.Properties.CorrelationId = correlationId;
            amqpMessage.ApplicationProperties.Map[MessageApplicationPropertyNames.OperationType] =
                DeviceOperations.GetOperationStatus;
            amqpMessage.ApplicationProperties.Map[MessageApplicationPropertyNames.OperationId] = operationId;
            var outcome = await client.AmqpSession.SendingLink
                          .SendMessageAsync(amqpMessage, new ArraySegment <byte>(Guid.NewGuid().ToByteArray()),
                                            TimeoutConstant).ConfigureAwait(false);

            var amqpResponse = await client.AmqpSession.ReceivingLink.ReceiveMessageAsync(TimeoutConstant)
                               .ConfigureAwait(false);

            client.AmqpSession.ReceivingLink.AcceptMessage(amqpResponse);
            string jsonResponse = await new StreamReader(amqpResponse.BodyStream).ReadToEndAsync()
                                  .ConfigureAwait(false);

            return(JsonConvert.DeserializeObject <RegistrationOperationStatus>(jsonResponse));
        }
 public override Task OpenConnectionAsync(
     AmqpClientConnection connection,
     bool useWebSocket,
     IWebProxy proxy,
     RemoteCertificateValidationCallback remoteCertificateValidationCallback,
     CancellationToken cancellationToken)
 {
     return(connection.OpenAsync(useWebSocket, null, proxy, remoteCertificateValidationCallback, cancellationToken));
 }
Exemplo n.º 4
0
        public override Task OpenConnectionAsync(
            AmqpClientConnection connection,
            bool useWebSocket,
            IWebProxy proxy,
            RemoteCertificateValidationCallback remoteCertificateValidationCallback,
            CancellationToken cancellationToken)
        {
            X509Certificate2 clientCert = _security.GetAuthenticationCertificate();

            return(connection.OpenAsync(useWebSocket, clientCert, proxy, remoteCertificateValidationCallback, cancellationToken));
        }
        private async Task <RegistrationOperationStatus> RegisterDeviceAsync(
            AmqpClientConnection client,
            string correlationId,
            DeviceRegistration deviceRegistration)
        {
            AmqpMessage amqpMessage = null;

            try
            {
                if (deviceRegistration == null)
                {
                    amqpMessage = AmqpMessage.Create(new MemoryStream(), true);
                }
                else
                {
                    var customContentStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(deviceRegistration)));
                    amqpMessage = AmqpMessage.Create(customContentStream, true);
                }

                amqpMessage.Properties.CorrelationId = correlationId;
                amqpMessage.ApplicationProperties.Map[MessageApplicationPropertyNames.OperationType]     = DeviceOperations.Register;
                amqpMessage.ApplicationProperties.Map[MessageApplicationPropertyNames.ForceRegistration] = false;

                Outcome outcome = await client.AmqpSession.SendingLink
                                  .SendMessageAsync(
                    amqpMessage,
                    new ArraySegment <byte>(Guid.NewGuid().ToByteArray()),
                    s_timeoutConstant)
                                  .ConfigureAwait(false);

                ValidateOutcome(outcome);

                AmqpMessage amqpResponse = await client.AmqpSession.ReceivingLink.ReceiveMessageAsync(s_timeoutConstant).ConfigureAwait(false);

                client.AmqpSession.ReceivingLink.AcceptMessage(amqpResponse);

                using (var streamReader = new StreamReader(amqpResponse.BodyStream))
                {
                    string jsonResponse = await streamReader
                                          .ReadToEndAsync()
                                          .ConfigureAwait(false);

                    RegistrationOperationStatus status = JsonConvert.DeserializeObject <RegistrationOperationStatus>(jsonResponse);
                    status.RetryAfter = ProvisioningErrorDetailsAmqp.GetRetryAfterFromApplicationProperties(amqpResponse, s_defaultOperationPoolingInterval);
                    return(status);
                }
            }
            finally
            {
                amqpMessage?.Dispose();
            }
        }
        private static async Task CreateLinksAsync(AmqpClientConnection connection, string linkEndpoint, string productInfo)
        {
            AmqpClientSession amqpDeviceSession = connection.CreateSession();
            await amqpDeviceSession.OpenAsync(s_timeoutConstant).ConfigureAwait(false);

            AmqpClientLink amqpReceivingLink = amqpDeviceSession.CreateReceivingLink(linkEndpoint);

            amqpReceivingLink.AddClientVersion(productInfo);
            amqpReceivingLink.AddApiVersion(ClientApiVersionHelper.ApiVersion);

            await amqpReceivingLink.OpenAsync(s_timeoutConstant).ConfigureAwait(false);

            AmqpClientLink amqpSendingLink = amqpDeviceSession.CreateSendingLink(linkEndpoint);

            amqpSendingLink.AddClientVersion(productInfo);
            amqpSendingLink.AddApiVersion(ClientApiVersionHelper.ApiVersion);

            await amqpSendingLink.OpenAsync(s_timeoutConstant).ConfigureAwait(false);
        }
        private async Task <RegistrationOperationStatus> OperationStatusLookupAsync(
            AmqpClientConnection client,
            string operationId,
            string correlationId,
            CancellationToken cancellationToken)
        {
            using var amqpMessage = AmqpMessage.Create(new AmqpValue { Value = DeviceOperations.GetOperationStatus });

            amqpMessage.Properties.CorrelationId = correlationId;
            amqpMessage.ApplicationProperties.Map[MessageApplicationPropertyNames.OperationType] =
                DeviceOperations.GetOperationStatus;
            amqpMessage.ApplicationProperties.Map[MessageApplicationPropertyNames.OperationId] = operationId;

            Outcome outcome = await client.AmqpSession.SendingLink
                              .SendMessageAsync(
                amqpMessage,
                new ArraySegment <byte>(Guid.NewGuid().ToByteArray()),
                cancellationToken)
                              .ConfigureAwait(false);

            ValidateOutcome(outcome);

            AmqpMessage amqpResponse = await client.AmqpSession.ReceivingLink
                                       .ReceiveMessageAsync(cancellationToken)
                                       .ConfigureAwait(false);

            client.AmqpSession.ReceivingLink.AcceptMessage(amqpResponse);

            using var streamReader = new StreamReader(amqpResponse.BodyStream);

            string jsonResponse = await streamReader.ReadToEndAsync().ConfigureAwait(false);

            RegistrationOperationStatus status = JsonConvert.DeserializeObject <RegistrationOperationStatus>(jsonResponse);

            status.RetryAfter = ProvisioningErrorDetailsAmqp.GetRetryAfterFromApplicationProperties(amqpResponse, s_defaultOperationPollingInterval);

            return(status);
        }
Exemplo n.º 8
0
 public override Task OpenConnectionAsync(AmqpClientConnection connection, TimeSpan timeout, bool useWebSocket, IWebProxy proxy)
 {
     return(connection.OpenAsync(timeout, useWebSocket, null, null, proxy));
 }
        public override async Task <DeviceRegistrationResult> RegisterAsync(
            ProvisioningTransportRegisterMessage message,
            CancellationToken cancellationToken)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, $"{nameof(ProvisioningTransportHandlerAmqp)}.{nameof(RegisterAsync)}");
            }

            cancellationToken.ThrowIfCancellationRequested();

            try
            {
                AmqpAuthStrategy authStrategy;

                if (message.Security is SecurityClientHsmTpm)
                {
                    authStrategy = new AmqpAuthStrategyTpm((SecurityClientHsmTpm)message.Security);
                }
                else if (message.Security is SecurityClientHsmX509)
                {
                    authStrategy = new AmqpAuthStrategyX509((SecurityClientHsmX509)message.Security);
                }
                else
                {
                    throw new NotSupportedException(
                              $"{nameof(message.Security)} must be of type {nameof(SecurityClientHsmTpm)} " +
                              $"or {nameof(SecurityClientHsmX509)}");
                }

                if (Logging.IsEnabled)
                {
                    Logging.Associate(authStrategy, this);
                }

                bool useWebSocket = (FallbackType == TransportFallbackType.WebSocketOnly);

                var builder = new UriBuilder()
                {
                    Scheme = useWebSocket ? WebSocketConstants.Scheme : AmqpConstants.SchemeAmqps,
                    Host   = message.GlobalDeviceEndpoint,
                    Port   = useWebSocket ? WebSocketConstants.Port : AmqpConstants.DefaultSecurePort
                };

                string registrationId = message.Security.GetRegistrationID();
                string linkEndpoint   = $"{message.IdScope}/registrations/{registrationId}";

                AmqpClientConnection connection = authStrategy.CreateConnection(builder.Uri, linkEndpoint);
                await authStrategy.OpenConnectionAsync(connection, TimeoutConstant, useWebSocket).ConfigureAwait(false);

                cancellationToken.ThrowIfCancellationRequested();

                await CreateLinksAsync(connection, linkEndpoint, message.ProductInfo).ConfigureAwait(false);

                cancellationToken.ThrowIfCancellationRequested();

                string correlationId = new Guid().ToString();
                RegistrationOperationStatus operation =
                    await RegisterDeviceAsync(connection, correlationId).ConfigureAwait(false);

                // Poll with operationId until registration complete.
                int    attempts    = 0;
                string operationId = operation.OperationId;

                // Poll with operationId until registration complete.
                while (string.CompareOrdinal(operation.Status, RegistrationOperationStatus.OperationStatusAssigning) == 0 ||
                       string.CompareOrdinal(operation.Status, RegistrationOperationStatus.OperationStatusUnassigned) == 0)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    await Task.Delay(
                        operation.RetryAfter ??
                        DefaultOperationPoolingIntervalMilliseconds).ConfigureAwait(false);

                    cancellationToken.ThrowIfCancellationRequested();

                    operation = await OperationStatusLookupAsync(
                        connection,
                        operationId,
                        correlationId).ConfigureAwait(false);

                    attempts++;
                }

                if (string.CompareOrdinal(operation.Status, RegistrationOperationStatus.OperationStatusAssigned) == 0)
                {
                    authStrategy.SaveCredentials(operation);
                }

                return(ConvertToProvisioningRegistrationResult(operation.RegistrationStatus));
            }
            // TODO: Catch only expected exceptions from Amqp.
            catch (Exception ex)
            {
                if (Logging.IsEnabled)
                {
                    Logging.Error(
                        this,
                        $"{nameof(ProvisioningTransportHandlerAmqp)} threw exception {ex}",
                        nameof(RegisterAsync));
                }

                // TODO: Extract trackingId from the exception.
                throw new ProvisioningTransportException($"AMQP transport exception", true, "", ex);
            }
            finally
            {
                if (Logging.IsEnabled)
                {
                    Logging.Exit(this, $"{nameof(ProvisioningTransportHandlerAmqp)}.{nameof(RegisterAsync)}");
                }
            }
        }
 public abstract Task OpenConnectionAsync(AmqpClientConnection connection, TimeSpan timeout, bool useWebSocket, IWebProxy proxy, RemoteCertificateValidationCallback remoteCertificateValidationCallback);
Exemplo n.º 11
0
 public abstract Task OpenConnectionAsync(
     AmqpClientConnection connection,
     bool useWebSocket,
     IWebProxy proxy,
     RemoteCertificateValidationCallback remoteCertificateValidationCallback,
     CancellationToken cancellationToken);
 public abstract Task OpenConnectionAsync(AmqpClientConnection connection, TimeSpan timeout, bool useWebSocket, IWebProxy proxy);
Exemplo n.º 13
0
        public override Task OpenConnectionAsync(AmqpClientConnection connection, TimeSpan timeout, bool useWebSocket, IWebProxy proxy)
        {
            X509Certificate2 clientCert = _security.GetAuthenticationCertificate();

            return(connection.OpenAsync(timeout, useWebSocket, clientCert, _security.CertificateValidationCallback, proxy));
        }
        /// <summary>
        /// Registers a device described by the message.
        /// </summary>
        /// <param name="message">The provisioning message.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>The registration result.</returns>
        public override async Task <DeviceRegistrationResult> RegisterAsync(
            ProvisioningTransportRegisterMessage message,
            CancellationToken cancellationToken)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, $"{nameof(ProvisioningTransportHandlerAmqp)}.{nameof(RegisterAsync)}");
            }

            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            cancellationToken.ThrowIfCancellationRequested();

            try
            {
                AmqpAuthStrategy authStrategy;

                if (message.Security is SecurityProviderTpm)
                {
                    authStrategy = new AmqpAuthStrategyTpm((SecurityProviderTpm)message.Security);
                }
                else if (message.Security is SecurityProviderX509)
                {
                    authStrategy = new AmqpAuthStrategyX509((SecurityProviderX509)message.Security);
                }
                else if (message.Security is SecurityProviderSymmetricKey)
                {
                    authStrategy = new AmqpAuthStrategySymmetricKey((SecurityProviderSymmetricKey)message.Security);
                }
                else
                {
                    throw new NotSupportedException(
                              $"{nameof(message.Security)} must be of type {nameof(SecurityProviderTpm)}, " +
                              $"{nameof(SecurityProviderX509)} or {nameof(SecurityProviderSymmetricKey)}");
                }

                if (Logging.IsEnabled)
                {
                    Logging.Associate(authStrategy, this);
                }

                bool useWebSocket = (FallbackType == TransportFallbackType.WebSocketOnly);

                var builder = new UriBuilder()
                {
                    Scheme = useWebSocket ? WebSocketConstants.Scheme : AmqpConstants.SchemeAmqps,
                    Host   = message.GlobalDeviceEndpoint,
                    Port   = Port,
                };

                string registrationId = message.Security.GetRegistrationID();
                string linkEndpoint   = $"{message.IdScope}/registrations/{registrationId}";

                using AmqpClientConnection connection = authStrategy.CreateConnection(builder.Uri, message.IdScope);
                await authStrategy.OpenConnectionAsync(connection, s_timeoutConstant, useWebSocket, Proxy, RemoteCertificateValidationCallback).ConfigureAwait(false);

                cancellationToken.ThrowIfCancellationRequested();

                await CreateLinksAsync(
                    connection,
                    linkEndpoint,
                    message.ProductInfo).ConfigureAwait(false);

                cancellationToken.ThrowIfCancellationRequested();

                string             correlationId      = Guid.NewGuid().ToString();
                DeviceRegistration deviceRegistration = (message.Payload != null && message.Payload.Length > 0) ? new DeviceRegistration {
                    Payload = new JRaw(message.Payload)
                } : null;

                RegistrationOperationStatus operation = await RegisterDeviceAsync(connection, correlationId, deviceRegistration).ConfigureAwait(false);

                // Poll with operationId until registration complete.
                int    attempts    = 0;
                string operationId = operation.OperationId;

                // Poll with operationId until registration complete.
                while (string.CompareOrdinal(operation.Status, RegistrationOperationStatus.OperationStatusAssigning) == 0 ||
                       string.CompareOrdinal(operation.Status, RegistrationOperationStatus.OperationStatusUnassigned) == 0)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    await Task.Delay(
                        operation.RetryAfter ?? RetryJitter.GenerateDelayWithJitterForRetry(s_defaultOperationPoolingInterval),
                        cancellationToken).ConfigureAwait(false);

                    try
                    {
                        operation = await OperationStatusLookupAsync(
                            connection,
                            operationId,
                            correlationId).ConfigureAwait(false);
                    }
                    catch (ProvisioningTransportException e) when(e.ErrorDetails is ProvisioningErrorDetailsAmqp amqp && e.IsTransient)
                    {
                        operation.RetryAfter = amqp.RetryAfter;
                    }

                    attempts++;
                }

                if (string.CompareOrdinal(operation.Status, RegistrationOperationStatus.OperationStatusAssigned) == 0)
                {
                    authStrategy.SaveCredentials(operation);
                }

                await connection.CloseAsync(s_timeoutConstant).ConfigureAwait(false);

                return(ConvertToProvisioningRegistrationResult(operation.RegistrationState));
            }
            catch (Exception ex) when(!(ex is ProvisioningTransportException))
            {
                if (Logging.IsEnabled)
                {
                    Logging.Error(
                        this,
                        $"{nameof(ProvisioningTransportHandlerAmqp)} threw exception {ex}",
                        nameof(RegisterAsync));
                }

                throw new ProvisioningTransportException($"AMQP transport exception", ex, true);
            }
            finally
            {
                if (Logging.IsEnabled)
                {
                    Logging.Exit(this, $"{nameof(ProvisioningTransportHandlerAmqp)}.{nameof(RegisterAsync)}");
                }
            }
        }
        public override Task OpenConnectionAsync(AmqpClientConnection connection, TimeSpan timeout, bool useWebSocket)
        {
            X509Certificate2 clientCert = _security.GetAuthenticationCertificate();

            return(connection.OpenAsync(timeout, useWebSocket, clientCert));
        }
 public AmqpClientSession(AmqpClientConnection amqpTestConnection)
 {
     _amqpConnection     = amqpTestConnection;
     AmqpSessionSettings = new AmqpSessionSettings();
 }
Exemplo n.º 17
0
 public override Task OpenConnectionAsync(AmqpClientConnection connection, TimeSpan timeout, bool useWebSocket, IWebProxy proxy, RemoteCertificateValidationCallback remoteCertificateValidationCallback)
 {
     return(connection.OpenAsync(timeout, useWebSocket, null, proxy, remoteCertificateValidationCallback));
 }