TimeSpan DeriveKeepAliveTimeout(ConnectPacket packet) { TimeSpan timeout = TimeSpan.FromSeconds(packet.KeepAliveInSeconds * 1.5); TimeSpan? maxTimeout = this.settings.MaxKeepAliveTimeout; if (maxTimeout.HasValue && (timeout > maxTimeout.Value || timeout == TimeSpan.Zero)) { if (MqttIotHubAdapterEventSource.Log.IsVerboseEnabled) { MqttIotHubAdapterEventSource.Log.Verbose(string.Format("Requested Keep Alive timeout is longer than the max allowed. Limiting to max value of {0}.", maxTimeout.Value), null); } return maxTimeout.Value; } return timeout; }
async void Connect(IChannelHandlerContext context) { var connectPacket = new ConnectPacket { ClientId = this.deviceId, HasUsername = true, Username = this.iotHubHostName + "/" + this.deviceId, HasPassword = true, Password = this.password, KeepAliveInSeconds = this.mqttTransportSettings.KeepAliveInSeconds, CleanSession = this.mqttTransportSettings.CleanSession, HasWill = this.mqttTransportSettings.HasWill }; if (connectPacket.HasWill) { Message message = this.willMessage.Message; QualityOfService publishToServerQoS = this.mqttTransportSettings.PublishToServerQoS; string topicName = string.Format(TelemetryTopicFormat, this.deviceId); PublishPacket will = await Util.ComposePublishPacketAsync(context, message, publishToServerQoS, topicName); connectPacket.WillMessage = will.Payload; connectPacket.WillQualityOfService = this.willMessage.QoS; connectPacket.WillRetain = false; connectPacket.WillTopicName = will.TopicName; } this.stateFlags = StateFlags.Connecting; await Util.WriteMessageAsync(context, connectPacket, ShutdownOnWriteErrorHandler); this.lastChannelActivityTime = DateTime.UtcNow; this.ScheduleKeepConnectionAlive(context); this.ScheduleCheckConnectTimeout(context); }
/// <summary> /// Performs complete initialization of <see cref="MqttIotHubAdapter" /> 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, "CONNECT has been received in current session already. Only one CONNECT is expected per session."); return; } this.stateFlags = StateFlags.ProcessingConnect; AuthenticationResult authResult = await this.authProvider.AuthenticateAsync(packet.ClientId, packet.Username, packet.Password, context.Channel.RemoteAddress); if (!authResult.IsSuccessful) { connAckSent = true; await Util.WriteMessageAsync(context, new ConnAckPacket { ReturnCode = ConnectReturnCode.RefusedNotAuthorized }); PerformanceCounters.ConnectionFailedAuthPerSecond.Increment(); ShutdownOnError(context, "Authentication failed."); return; } this.deviceId = authResult.DeviceId; this.iotHubClient = await this.deviceClientFactory(authResult); bool sessionPresent = await this.EstablishSessionStateAsync(this.deviceId, packet.CleanSession); this.keepAliveTimeout = this.DeriveKeepAliveTimeout(packet); if (packet.HasWill) { var will = new PublishPacket(packet.WillQualityOfService, false, packet.WillRetain); will.TopicName = packet.WillTopicName; will.Payload = packet.WillMessage; this.willPacket = will; } this.sessionContext = new Dictionary<string, string> { { DeviceIdParam, this.deviceId } }; this.StartReceiving(context); 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 (MqttIotHubAdapterEventSource.Log.IsVerboseEnabled) { MqttIotHubAdapterEventSource.Log.Verbose("Error sending 'Server Unavailable' CONNACK.", ex.ToString()); } } } ShutdownOnError(context, "CONNECT", exception); } }