// This call is executed over AMQP. public override async Task SendAsync(string deviceId, string moduleId, Message message) { Logging.Enter(this, $"Sending message with Id [{message?.MessageId}] for device {deviceId}, module {moduleId}", nameof(SendAsync)); if (string.IsNullOrWhiteSpace(deviceId)) { throw new ArgumentNullException(nameof(deviceId)); } if (string.IsNullOrWhiteSpace(moduleId)) { throw new ArgumentNullException(nameof(moduleId)); } if (message == null) { throw new ArgumentNullException(nameof(message)); } if (_clientOptions?.SdkAssignsMessageId == SdkAssignsMessageId.WhenUnset && message.MessageId == null) { message.MessageId = Guid.NewGuid().ToString(); } if (message.IsBodyCalled) { message.ResetBody(); } using AmqpMessage amqpMessage = MessageConverter.MessageToAmqpMessage(message); amqpMessage.Properties.To = "/devices/" + WebUtility.UrlEncode(deviceId) + "/modules/" + WebUtility.UrlEncode(moduleId) + "/messages/deviceBound"; try { SendingAmqpLink sendingLink = await GetSendingLinkAsync().ConfigureAwait(false); Outcome outcome = await sendingLink .SendMessageAsync( amqpMessage, IotHubConnection.GetNextDeliveryTag(ref _sendingDeliveryTag), AmqpConstants.NullBinary, OperationTimeout) .ConfigureAwait(false); Logging.Info(this, $"Outcome was: {outcome?.DescriptorName}", nameof(SendAsync)); if (outcome.DescriptorCode != Accepted.Code) { throw AmqpErrorMapper.GetExceptionFromOutcome(outcome); } } catch (Exception ex) when(!ex.IsFatal()) { Logging.Error(this, $"{nameof(SendAsync)} threw an exception: {ex}", nameof(SendAsync)); throw AmqpClientHelper.ToIotHubClientContract(ex); } finally { Logging.Exit(this, $"Sending message with Id [{message?.MessageId}] for device {deviceId}, module {moduleId}", nameof(SendAsync)); } }
public async override Task SendAsync(string deviceId, Message message, TimeSpan?timeout = null) { if (string.IsNullOrWhiteSpace(deviceId)) { throw new ArgumentNullException(nameof(deviceId)); } if (message == null) { throw new ArgumentNullException(nameof(message)); } timeout ??= OperationTimeout; using AmqpMessage amqpMessage = message.ToAmqpMessage(); amqpMessage.Properties.To = "/devices/" + WebUtility.UrlEncode(deviceId) + "/messages/deviceBound"; try { SendingAmqpLink sendingLink = await GetSendingLinkAsync().ConfigureAwait(false); Outcome outcome = await sendingLink .SendMessageAsync(amqpMessage, IotHubConnection.GetNextDeliveryTag(ref _sendingDeliveryTag), AmqpConstants.NullBinary, timeout.Value) .ConfigureAwait(false); if (outcome.DescriptorCode != Accepted.Code) { throw AmqpErrorMapper.GetExceptionFromOutcome(outcome); } } catch (Exception ex) when(!(ex is TimeoutException) && !ex.IsFatal()) { throw AmqpClientHelper.ToIotHubClientContract(ex); } }
public override async Task <FileNotification> ReceiveAsync(TimeSpan timeout) { try { ReceivingAmqpLink receivingLink = await this.faultTolerantReceivingLink.GetReceivingLinkAsync(); AmqpMessage amqpMessage = await receivingLink.ReceiveMessageAsync(timeout); if (amqpMessage != null) { using (amqpMessage) { AmqpClientHelper.ValidateContentType(amqpMessage, CommonConstants.FileNotificationContentType); var fileNotification = await AmqpClientHelper.GetObjectFromAmqpMessageAsync <FileNotification>(amqpMessage); fileNotification.LockToken = new Guid(amqpMessage.DeliveryTag.Array).ToString(); return(fileNotification); } } return(null); } catch (Exception exception) { if (exception.IsFatal()) { throw; } throw AmqpClientHelper.ToIotHubClientContract(exception); } }
internal static async Task DisposeMessageAsync(FaultTolerantAmqpObject <ReceivingAmqpLink> faultTolerantReceivingLink, string lockToken, Outcome outcome, bool batchable) { var deliveryTag = IotHubConnection.ConvertToDeliveryTag(lockToken); Outcome disposeOutcome; try { ReceivingAmqpLink deviceBoundReceivingLink = await faultTolerantReceivingLink.GetReceivingLinkAsync().ConfigureAwait(false); disposeOutcome = await deviceBoundReceivingLink.DisposeMessageAsync(deliveryTag, outcome, batchable, IotHubConnection.DefaultOperationTimeout).ConfigureAwait(false); } catch (Exception exception) { if (exception.IsFatal()) { throw; } throw AmqpClientHelper.ToIotHubClientContract(exception); } if (disposeOutcome.DescriptorCode != Accepted.Code) { throw AmqpErrorMapper.GetExceptionFromOutcome(disposeOutcome); } }
async Task DisposeMessageAsync(string lockToken, Outcome outcome) { var deliveryTag = IotHubConnection.ConvertToDeliveryTag(lockToken); Outcome disposeOutcome; try { ReceivingAmqpLink deviceBoundReceivingLink = await this.GetReceivingLinkAsync(); disposeOutcome = await deviceBoundReceivingLink.DisposeMessageAsync(deliveryTag, outcome, batchable : true, timeout : this.OperationTimeout); } catch (Exception exception) { if (exception.IsFatal()) { throw; } throw AmqpClientHelper.ToIotHubClientContract(exception); } if (disposeOutcome.DescriptorCode != Accepted.Code) { throw AmqpErrorMapper.GetExceptionFromOutcome(disposeOutcome); } }
public override Task CompleteAsync(FileNotification fileNotification) { return(AmqpClientHelper.DisposeMessageAsync( this.faultTolerantReceivingLink, fileNotification.LockToken, AmqpConstants.AcceptedOutcome, false)); }
public override Task AbandonAsync(FeedbackBatch feedback) { return(AmqpClientHelper.DisposeMessageAsync( _faultTolerantReceivingLink, feedback.LockToken, AmqpConstants.ReleasedOutcome, true)); }
public AmqpFeedbackReceiver(IotHubConnection iotHubConnection) { Connection = iotHubConnection; OpenTimeout = IotHubConnection.DefaultOpenTimeout; OperationTimeout = IotHubConnection.DefaultOperationTimeout; _receivingPath = AmqpClientHelper.GetReceivingPath(EndpointKind.Feedback); _faultTolerantReceivingLink = new FaultTolerantAmqpObject <ReceivingAmqpLink>(CreateReceivingLinkAsync, Connection.CloseLink); }
public override Task CompleteAsync(FeedbackBatch feedback) { return(AmqpClientHelper.DisposeMessageAsync( this.faultTolerantReceivingLink, feedback.LockToken, AmqpConstants.AcceptedOutcome, true)); }
public override Task AbandonAsync(FileNotification fileNotification) { return(AmqpClientHelper.DisposeMessageAsync( _faultTolerantReceivingLink, fileNotification.LockToken, AmqpConstants.ReleasedOutcome, false)); }
public AmqpFileNotificationReceiver(IotHubConnection iotHubConnection) { this.Connection = iotHubConnection; this.OpenTimeout = IotHubConnection.DefaultOpenTimeout; this.OperationTimeout = IotHubConnection.DefaultOperationTimeout; this.receivingPath = AmqpClientHelper.GetReceivingPath(EndpointKind.FileNotification); this.faultTolerantReceivingLink = new FaultTolerantAmqpObject <ReceivingAmqpLink>(this.CreateReceivingLinkAsync, this.Connection.CloseLink); }
public override Task AbandonAsync(FeedbackBatch feedback) { return(AmqpClientHelper.DisposeMessageAsync( _faultTolerantReceivingLink, feedback.LockToken, AmqpConstants.ReleasedOutcome, false)); // Feedback messages are sent by the service one at a time, so batching the acks is pointless }
public override Task CompleteAsync(FeedbackBatch feedback, CancellationToken cancellationToken) { return(AmqpClientHelper.DisposeMessageAsync( _faultTolerantReceivingLink, feedback.LockToken, AmqpConstants.AcceptedOutcome, false, // Feedback messages are sent by the service one at a time, so batching the acks is pointless cancellationToken)); }
public override async Task <FeedbackBatch> ReceiveAsync(CancellationToken cancellationToken) { Logging.Enter(this, nameof(ReceiveAsync)); try { cancellationToken.ThrowIfCancellationRequested(); ReceivingAmqpLink receivingLink = await _faultTolerantReceivingLink.GetReceivingLinkAsync().ConfigureAwait(false); AmqpMessage amqpMessage = await receivingLink.ReceiveMessageAsync(cancellationToken).ConfigureAwait(false); Logging.Info(this, $"Message received is [{amqpMessage}]", nameof(ReceiveAsync)); if (amqpMessage != null) { using (amqpMessage) { AmqpClientHelper.ValidateContentType(amqpMessage, CommonConstants.BatchedFeedbackContentType); IEnumerable <FeedbackRecord> records = await AmqpClientHelper .GetObjectFromAmqpMessageAsync <IEnumerable <FeedbackRecord> >(amqpMessage).ConfigureAwait(false); return(new FeedbackBatch { EnqueuedTime = (DateTime)amqpMessage.MessageAnnotations.Map[MessageSystemPropertyNames.EnqueuedTime], LockToken = new Guid(amqpMessage.DeliveryTag.Array).ToString(), Records = records, UserId = Encoding.UTF8.GetString(amqpMessage.Properties.UserId.Array, amqpMessage.Properties.UserId.Offset, amqpMessage.Properties.UserId.Count) }); } } return(null); } catch (Exception exception) { Logging.Error(this, exception, nameof(ReceiveAsync)); if (exception.IsFatal()) { throw; } throw AmqpClientHelper.ToIotHubClientContract(exception); } finally { Logging.Exit(this, nameof(ReceiveAsync)); } }
public async override Task SendAsync(string deviceId, Message message, TimeSpan?timeout = null) { if (string.IsNullOrWhiteSpace(deviceId)) { throw new ArgumentException("Value should be non null and non empty", "deviceId"); } if (message == null) { throw new ArgumentNullException("message"); } Outcome outcome; using (AmqpMessage amqpMessage = message.ToAmqpMessage()) { amqpMessage.Properties.To = "/devices/" + WebUtility.UrlEncode(deviceId) + "/messages/deviceBound"; try { SendingAmqpLink sendingLink = await GetSendingLinkAsync().ConfigureAwait(false); if (timeout != null) { outcome = await sendingLink.SendMessageAsync(amqpMessage, IotHubConnection.GetNextDeliveryTag(ref sendingDeliveryTag), AmqpConstants.NullBinary, (TimeSpan)timeout).ConfigureAwait(false); } else { outcome = await sendingLink.SendMessageAsync(amqpMessage, IotHubConnection.GetNextDeliveryTag(ref sendingDeliveryTag), AmqpConstants.NullBinary, OperationTimeout).ConfigureAwait(false); } } catch (TimeoutException exception) { throw exception; } catch (Exception exception) { if (exception.IsFatal()) { throw; } throw AmqpClientHelper.ToIotHubClientContract(exception); } } if (outcome.DescriptorCode != Accepted.Code) { throw AmqpErrorMapper.GetExceptionFromOutcome(outcome); } }
public override async Task <FeedbackBatch> ReceiveAsync(TimeSpan timeout) { try { ReceivingAmqpLink receivingLink = await this.GetReceivingLinkAsync(); AmqpMessage amqpMessage = await receivingLink.ReceiveMessageAsync(timeout); if (amqpMessage != null) { using (amqpMessage) { string contentType = amqpMessage.Properties.ContentType.ToString(); if (!string.Equals(contentType, CommonConstants.BatchedFeedbackContentType, StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException("Unsupported content type: {0}".FormatInvariant(contentType)); } using (var reader = new StreamReader(amqpMessage.BodyStream, Encoding.UTF8)) { string jsonString = await reader.ReadToEndAsync(); var records = JsonConvert.DeserializeObject <IEnumerable <FeedbackRecord> >(jsonString); return(new FeedbackBatch { EnqueuedTime = (DateTime)amqpMessage.MessageAnnotations.Map[MessageSystemPropertyNames.EnqueuedTime], LockToken = new Guid(amqpMessage.DeliveryTag.Array).ToString(), Records = records, UserId = Encoding.UTF8.GetString(amqpMessage.Properties.UserId.Array, amqpMessage.Properties.UserId.Offset, amqpMessage.Properties.UserId.Count) }); } } } return(null); } catch (Exception exception) { if (exception.IsFatal()) { throw; } throw AmqpClientHelper.ToIotHubClientContract(exception); } }
public override async Task <FileNotification> ReceiveAsync(CancellationToken cancellationToken) { Logging.Enter(this, nameof(ReceiveAsync)); try { cancellationToken.ThrowIfCancellationRequested(); ReceivingAmqpLink receivingLink = await _faultTolerantReceivingLink.GetReceivingLinkAsync().ConfigureAwait(false); AmqpMessage amqpMessage = await receivingLink.ReceiveMessageAsync(cancellationToken).ConfigureAwait(false); Logging.Info(this, $"Message received is [{amqpMessage}]", nameof(ReceiveAsync)); if (amqpMessage != null) { using (amqpMessage) { AmqpClientHelper.ValidateContentType(amqpMessage, CommonConstants.FileNotificationContentType); FileNotification fileNotification = await AmqpClientHelper.GetObjectFromAmqpMessageAsync <FileNotification>(amqpMessage).ConfigureAwait(false); fileNotification.LockToken = new Guid(amqpMessage.DeliveryTag.Array).ToString(); return(fileNotification); } } return(null); } catch (Exception exception) { Logging.Error(this, exception, nameof(ReceiveAsync)); if (exception.IsFatal()) { throw; } throw AmqpClientHelper.ToIotHubClientContract(exception); } finally { Logging.Exit(this, nameof(ReceiveAsync)); } }
public override async Task SendAsync(string deviceId, string moduleId, Message message) { if (string.IsNullOrWhiteSpace(deviceId)) { throw new ArgumentNullException(nameof(deviceId)); } if (string.IsNullOrWhiteSpace(moduleId)) { throw new ArgumentNullException(nameof(moduleId)); } if (message == null) { throw new ArgumentNullException(nameof(message)); } Outcome outcome; using (AmqpMessage amqpMessage = message.ToAmqpMessage()) { amqpMessage.Properties.To = "/devices/" + WebUtility.UrlEncode(deviceId) + "/modules/" + WebUtility.UrlEncode(moduleId) + "/messages/deviceBound"; try { SendingAmqpLink sendingLink = await this.GetSendingLinkAsync().ConfigureAwait(false); outcome = await sendingLink.SendMessageAsync(amqpMessage, IotHubConnection.GetNextDeliveryTag(ref this.sendingDeliveryTag), AmqpConstants.NullBinary, this.OperationTimeout).ConfigureAwait(false); } catch (Exception exception) { if (exception.IsFatal()) { throw; } throw AmqpClientHelper.ToIotHubClientContract(exception); } } if (outcome.DescriptorCode != Accepted.Code) { throw AmqpErrorMapper.GetExceptionFromOutcome(outcome); } }
public override async Task <FeedbackBatch> ReceiveAsync(TimeSpan timeout) { try { ReceivingAmqpLink receivingLink = await faultTolerantReceivingLink.GetReceivingLinkAsync().ConfigureAwait(false); AmqpMessage amqpMessage = await receivingLink.ReceiveMessageAsync(timeout).ConfigureAwait(false); if (amqpMessage != null) { using (amqpMessage) { AmqpClientHelper.ValidateContentType(amqpMessage, CommonConstants.BatchedFeedbackContentType); var records = await AmqpClientHelper.GetObjectFromAmqpMessageAsync <IEnumerable <FeedbackRecord> >(amqpMessage).ConfigureAwait(false); return(new FeedbackBatch { EnqueuedTime = (DateTime)amqpMessage.MessageAnnotations.Map[MessageSystemPropertyNames.EnqueuedTime], LockToken = new Guid(amqpMessage.DeliveryTag.Array).ToString(), Records = records, UserId = Encoding.UTF8.GetString(amqpMessage.Properties.UserId.Array, amqpMessage.Properties.UserId.Offset, amqpMessage.Properties.UserId.Count) }); } } return(null); } catch (Exception exception) { if (exception.IsFatal()) { throw; } throw AmqpClientHelper.ToIotHubClientContract(exception); } }
private async Task <AmqpSession> CreateSessionAsync(TimeSpan timeout) { Logging.Enter(this, timeout, nameof(CreateSessionAsync)); TransportBase transport = null; try { var timeoutHelper = new TimeoutHelper(timeout); _refreshTokenTimer.Cancel(); AmqpSettings amqpSettings = CreateAmqpSettings(); if (_useWebSocketOnly) { // Try only AMQP transport over WebSocket transport = _clientWebSocketTransport = (ClientWebSocketTransport) await CreateClientWebSocketTransportAsync(timeoutHelper.RemainingTime()) .ConfigureAwait(false); } else { TlsTransportSettings tlsTransportSettings = CreateTlsTransportSettings(); var amqpTransportInitiator = new AmqpTransportInitiator(amqpSettings, tlsTransportSettings); try { transport = await amqpTransportInitiator.ConnectTaskAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); } catch (Exception e) when(!(e is AuthenticationException)) { Logging.Error(this, e, nameof(CreateSessionAsync)); if (Fx.IsFatal(e)) { throw; } // AMQP transport over TCP failed. Retry AMQP transport over WebSocket if (timeoutHelper.RemainingTime() != TimeSpan.Zero) { transport = _clientWebSocketTransport = (ClientWebSocketTransport) await CreateClientWebSocketTransportAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); } else { throw; } } } Logging.Info(this, $"Initialized {nameof(TransportBase)}, ws={_useWebSocketOnly}"); var amqpConnectionSettings = new AmqpConnectionSettings { MaxFrameSize = AmqpConstants.DefaultMaxFrameSize, ContainerId = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture), // Use a human readable link name to help with debugging HostName = ConnectionString.AmqpEndpoint.Host, }; var amqpConnection = new AmqpConnection(transport, amqpSettings, amqpConnectionSettings); await amqpConnection.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); Logging.Info(this, $"{nameof(AmqpConnection)} opened."); var sessionSettings = new AmqpSessionSettings { Properties = new Fields(), }; try { AmqpSession amqpSession = amqpConnection.CreateSession(sessionSettings); await amqpSession.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); Logging.Info(this, $"{nameof(AmqpSession)} opened."); // This adds itself to amqpConnection.Extensions var cbsLink = new AmqpCbsLink(amqpConnection); await SendCbsTokenAsync(cbsLink, timeoutHelper.RemainingTime()).ConfigureAwait(false); return(amqpSession); } catch (Exception ex) when(!ex.IsFatal()) { Logging.Error(this, ex, nameof(CreateSessionAsync)); _clientWebSocketTransport?.Dispose(); _clientWebSocketTransport = null; if (amqpConnection.TerminalException != null) { throw AmqpClientHelper.ToIotHubClientContract(amqpConnection.TerminalException); } amqpConnection.SafeClose(ex); throw; } } finally { Logging.Exit(this, timeout, nameof(CreateSessionAsync)); } }
async Task <AmqpSession> CreateSessionAsync(TimeSpan timeout) { TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); this.refreshTokenTimer.Cancel(); var amqpSettings = CreateAmqpSettings(); TransportBase transport; if (this.useWebSocketOnly) { // Try only Amqp transport over WebSocket transport = await CreateClientWebSocketTransport(timeoutHelper.RemainingTime()).ConfigureAwait(false); } else { var tlsTransportSettings = this.CreateTlsTransportSettings(); var amqpTransportInitiator = new AmqpTransportInitiator(amqpSettings, tlsTransportSettings); try { transport = await amqpTransportInitiator.ConnectTaskAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } // Amqp transport over TCP failed. Retry Amqp transport over WebSocket if (timeoutHelper.RemainingTime() != TimeSpan.Zero) { transport = await CreateClientWebSocketTransport(timeoutHelper.RemainingTime()).ConfigureAwait(false); } else { throw; } } } AmqpConnectionSettings amqpConnectionSettings = new AmqpConnectionSettings() { MaxFrameSize = AmqpConstants.DefaultMaxFrameSize, ContainerId = Guid.NewGuid().ToString("N"), HostName = this.connectionString.AmqpEndpoint.Host }; var amqpConnection = new AmqpConnection(transport, amqpSettings, amqpConnectionSettings); await amqpConnection.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); var sessionSettings = new AmqpSessionSettings() { Properties = new Fields() }; try { var amqpSession = amqpConnection.CreateSession(sessionSettings); await amqpSession.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); // This adds itself to amqpConnection.Extensions var cbsLink = new AmqpCbsLink(amqpConnection); await SendCbsTokenAsync(cbsLink, timeoutHelper.RemainingTime()).ConfigureAwait(false); return(amqpSession); } catch (Exception ex) when(!ex.IsFatal()) { if (amqpConnection.TerminalException != null) { throw AmqpClientHelper.ToIotHubClientContract(amqpConnection.TerminalException); } amqpConnection.SafeClose(ex); throw; } }
private async Task <AmqpSession> CreateSessionAsync(TimeSpan timeout) { var timeoutHelper = new TimeoutHelper(timeout); _refreshTokenTimer.Cancel(); AmqpSettings amqpSettings = CreateAmqpSettings(); TransportBase transport; if (_useWebSocketOnly) { // Try only Amqp transport over WebSocket transport = await CreateClientWebSocketTransport(timeoutHelper.RemainingTime()).ConfigureAwait(false); } else { TlsTransportSettings tlsTransportSettings = CreateTlsTransportSettings(); var amqpTransportInitiator = new AmqpTransportInitiator(amqpSettings, tlsTransportSettings); try { transport = await amqpTransportInitiator.ConnectTaskAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); } #if !NETSTANDARD1_3 catch (AuthenticationException) { throw; } #endif catch (Exception e) { if (Fx.IsFatal(e)) { throw; } // Amqp transport over TCP failed. Retry Amqp transport over WebSocket if (timeoutHelper.RemainingTime() != TimeSpan.Zero) { transport = await CreateClientWebSocketTransport(timeoutHelper.RemainingTime()).ConfigureAwait(false); } else { throw; } } } var amqpConnectionSettings = new AmqpConnectionSettings { MaxFrameSize = AmqpConstants.DefaultMaxFrameSize, ContainerId = Guid.NewGuid() #if NETSTANDARD1_3 .ToString("N"), #else .ToString("N", CultureInfo.InvariantCulture), // Use a human readable link name to help with debugging #endif HostName = ConnectionString.AmqpEndpoint.Host, }; var amqpConnection = new AmqpConnection(transport, amqpSettings, amqpConnectionSettings); await amqpConnection.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); var sessionSettings = new AmqpSessionSettings { Properties = new Fields(), }; try { AmqpSession amqpSession = amqpConnection.CreateSession(sessionSettings); await amqpSession.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); // This adds itself to amqpConnection.Extensions var cbsLink = new AmqpCbsLink(amqpConnection); await SendCbsTokenAsync(cbsLink, timeoutHelper.RemainingTime()).ConfigureAwait(false); return(amqpSession); } catch (Exception ex) when(!ex.IsFatal()) { if (amqpConnection.TerminalException != null) { throw AmqpClientHelper.ToIotHubClientContract(amqpConnection.TerminalException); } amqpConnection.SafeClose(ex); throw; } }