private async void handleConnection(TcpClient connection) { var ep = connection.Client.RemoteEndPoint; Console.WriteLine("New Connection from {0}", ep); NetworkStream stream = connection.GetStream(); MqttMessage message = await MqttMessage.Read(stream, 5); if (message.Type != MessageType.Connect) { throw new MqttProtocolException("First packet not connect"); } //TODO: Non-clean sessions ConnAckMessage connAck = new ConnAckMessage(0, false); await connAck.Write(stream); ConnectMessage connectMessage = (ConnectMessage)message; double keepalive = ((ConnectMessage)message).KeepAlive * 1.5; String clientId = ((ConnectMessage)message).ClientId; if (String.IsNullOrEmpty(clientId)) { clientId = Guid.NewGuid().ToString(); } IMqttSession session = await sessionProvider.NewSession(clientId); Console.WriteLine("Client {0} connected from {1} ({2},{3})", clientId, ep, connectMessage.CleanSession, connectMessage.KeepAlive); connections.Add(session, connection); Task <MqttMessage> incoming = MqttMessage.Read(stream); Task <PendingMessage> outgoing = session.NextPending(null, 0); while (connection.Connected) { try { if (await Task.WhenAny(incoming, outgoing) == incoming) { try { message = incoming.Result; } catch (AggregateException e) { Console.WriteLine(e.InnerException.Message); connections.Remove(session); connection.Close(); continue; } catch (Exception e) { Console.WriteLine(e.Message); connections.Remove(session); connection.Close(); continue; } switch (message.Type) { case MessageType.Publish: await PublishReceived(session, stream, (PublishMessage)message); break; case MessageType.Disconnect: Console.WriteLine("Client {0} disconnected cleanly", clientId); connections.Remove(session); connection.Close(); //Skip reading the next message. Loop should exit. continue; case MessageType.Subscribe: await SubscribeReceived(session, stream, (SubscribeMessage)message); break; case MessageType.Unsubscribe: await sessionProvider.RemoveSubscriptions(session, ((UnsubscribeMessage)message).TopicFilters); await new UnsubAckMessage(((UnsubscribeMessage)message).PacketId).Write(stream); break; case MessageType.PubAck: string messageId = await session.PublishAcknowledged(((PubAckMessage)message).PacketId); if (messageId != null) { await storageProvider.ReleaseMessage(messageId); } break; case MessageType.PubRec: messageId = await session.PublishReceived(((PubRecMessage)message).PacketId); if (messageId != null) { await storageProvider.ReleaseMessage(messageId); } break; case MessageType.PubRel: await session.RemoveQoS2(((PubRelMessage)message).PacketId); await new PubCompMessage(((PubRelMessage)message).PacketId).Write(stream); break; case MessageType.PubComp: await session.PublishCompleted(((PubCompMessage)message).PacketId); break; case MessageType.PingReq: await new PingRespMessage().Write(stream); break; } incoming = MqttMessage.Read(stream); } else { PendingMessage pendingMessage = outgoing.Result; PendingPublishMessage pendingPublish = pendingMessage as PendingPublishMessage; if (pendingPublish != null) { var messageInfo = await storageProvider.GetMessage(pendingPublish.MessageId); message = new PublishMessage(pendingPublish.Duplicate, false, pendingPublish.QoS, messageInfo.Topic, messageInfo.Payload, pendingPublish.PacketId); } else { message = new PubRelMessage(pendingMessage.PacketId); } await message.Write(stream); outgoing = session.NextPending(pendingMessage, 5000); } } catch (Exception e) { Console.Out.WriteLine(e.Message); } } await sessionProvider.CloseSession(session); }