async void CloseServiceConnection(IChannelHandlerContext context, Exception cause, PublishPacket will) { if (!this.ConnectedToService) { // closure happened before IoT Hub connection was established or it was initiated due to disconnect return; } try { foreach (var publishProcessor in this.publishProcessors) { publishProcessor.Value.Complete(); } this.publishPubAckProcessor.Complete(); this.publishPubRecProcessor.Complete(); this.pubRelPubCompProcessor.Complete(); await Task.WhenAll( this.CompletePublishAsync(context, will), this.publishPubAckProcessor.Completion, this.publishPubRecProcessor.Completion, this.pubRelPubCompProcessor.Completion); IMessagingBridge bridge = this.messagingBridge; this.messagingBridge = null; await bridge.DisposeAsync(cause); } catch (Exception ex) { CommonEventSource.Log.Info("Failed to close IoT Hub Client cleanly.", ex.ToString(), this.ChannelId); } }
async void ShutdownOnReceiveError(Exception cause) { this.publishPubAckProcessor.Close(); foreach (var publishProcessor in this.publishProcessors) { publishProcessor.Value.Close(); } this.publishPubRecProcessor.Close(); this.pubRelPubCompProcessor.Close(); IMessagingBridge bridge = this.messagingBridge; if (bridge != null) { this.messagingBridge = null; try { await bridge.DisposeAsync(cause); } catch (Exception ex) { CommonEventSource.Log.Info("Failed to close IoT Hub Client cleanly: " + ex, this.ChannelId, this.Id); } } ShutdownOnError(this.capturedContext, ReceiveProcessingScope, cause); }
async Task CloseServiceConnection(IChannelHandlerContext context, Exception cause, PublishPacket will) { if (!this.ConnectedToService) { // closure happened before IoT Hub connection was established or it was initiated due to disconnect if (cause != null) { string causeScope = (string)cause.Data[OperationScopeExceptionDataKey] ?? "unknown"; CommonEventSource.Log.Error($"Connection closed while not fully connected. Scope: {causeScope}", cause, this.ChannelId, this.Id); } return; } try { this.publishPubAckProcessor.Close(); this.publishPubRecProcessor.Close(); this.pubRelPubCompProcessor.Close(); await Task.WhenAll( this.CompletePublishAsync(context, will), this.publishPubAckProcessor.Closed, this.publishPubRecProcessor.Closed, this.pubRelPubCompProcessor.Closed); } catch (Exception ex) { CommonEventSource.Log.Info("Failed to complete the processors: " + ex.ToString(), this.ChannelId, this.Id); } try { IMessagingBridge bridge = this.messagingBridge; if (this.messagingBridge != null) { this.messagingBridge = null; await bridge.DisposeAsync(cause); } } catch (Exception ex) { CommonEventSource.Log.Info("Failed to close IoT Hub Client cleanly: " + ex.ToString(), this.ChannelId, this.Id); } }
/// <summary> /// Performs complete initialization of <see cref="MqttAdapter" /> based on received CONNECT packet. /// </summary> /// <param name="context"><see cref="IChannelHandlerContext" /> instance.</param> /// <param name="packet">CONNECT packet.</param> async void Connect(IChannelHandlerContext context, ConnectPacket packet) { bool connAckSent = false; Exception exception = null; try { if (!this.IsInState(StateFlags.WaitingForConnect)) { ShutdownOnError(context, ConnectProcessingScope, new ProtocolGatewayException(ErrorCode.DuplicateConnectReceived, "CONNECT has been received in current session already. Only one CONNECT is expected per session.")); return; } this.stateFlags = StateFlags.ProcessingConnect; this.identity = await this.authProvider.GetAsync(packet.ClientId, packet.Username, packet.Password, context.Channel.RemoteAddress); if (!this.identity.IsAuthenticated) { CommonEventSource.Log.Info("ClientNotAuthenticated", this.ChannelId, $"Client ID: {packet.ClientId}; Username: {packet.Username}"); connAckSent = true; await Util.WriteMessageAsync(context, new ConnAckPacket { ReturnCode = ConnectReturnCode.RefusedNotAuthorized }); PerformanceCounters.ConnectionFailedAuthPerSecond.Increment(); ShutdownOnError(context, ConnectProcessingScope, new ProtocolGatewayException(ErrorCode.AuthenticationFailed, "Authentication failed.")); return; } CommonEventSource.Log.Info("ClientAuthenticated", this.ChannelId, this.Id); this.messagingBridge = await this.messagingBridgeFactory(this.identity, this.lifetimeCancellation.Token); bool sessionPresent = await this.EstablishSessionStateAsync(packet.CleanSession); this.keepAliveTimeout = this.DeriveKeepAliveTimeout(context, packet); if (packet.HasWill) { var will = new PublishPacket(packet.WillQualityOfService, false, packet.WillRetain); will.TopicName = packet.WillTopicName; will.Payload = packet.WillMessage; this.willPacket = will; } connAckSent = true; await Util.WriteMessageAsync(context, new ConnAckPacket { SessionPresent = sessionPresent, ReturnCode = ConnectReturnCode.Accepted }); this.CompleteConnect(context); } catch (Exception ex) { exception = ex; } if (exception != null) { if (!connAckSent) { try { await Util.WriteMessageAsync(context, new ConnAckPacket { ReturnCode = ConnectReturnCode.RefusedServerUnavailable }); } catch (Exception ex) { if (CommonEventSource.Log.IsVerboseEnabled) { CommonEventSource.Log.Verbose("Error sending 'Server Unavailable' CONNACK:" + ex, this.ChannelId, this.Id); } } } ShutdownOnError(context, ConnectProcessingScope, exception); } }