Beispiel #1
0
        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);
        }