Exemple #1
0
        public void AddInflightMessage(MqttMsgBase packet)
        {
            MqttMsgContext context = new MqttMsgContext();
            Del            d       = delegate() { return(packet.QosLevel == (byte)0x01 ? MqttMsgState.QueuedQos1 : MqttMsgState.QueuedQos2); };
            MqttMsgState   state   = packet.QosLevel == (byte)0x00 ? MqttMsgState.QueuedQos0 : d();

            context.State   = state;
            context.Message = packet;
            session.InflightMessages.Add(packet.MessageId, context);
        }
Exemple #2
0
 public void ChangeMsgState(ushort messageId, MqttMsgState state)
 {
     session.InflightMessages[messageId].State = state;
 }
        private static void EnqueueInflight(MqttClientConnection clientConnection, MqttMsgBase msg, MqttMsgFlow flow)
        {
            // enqueue is needed (or not)
            bool enqueue = true;

            // if it is a PUBLISH message with QoS Level 2
            if ((msg.Type == MqttMsgBase.MQTT_MSG_PUBLISH_TYPE) && (msg.QosLevel == MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE))
            {
                // if it is a PUBLISH message already received (it is in the inflight queue), the publisher
                // re-sent it because it didn't received the PUBREC. In clientConnection case, we have to re-send PUBREC

                // NOTE : I need to find on message id and flow because the broker could be publish/received
                //        to/from client and message id could be the same (one tracked by broker and the other by client)
                MqttMsgContextFinder msgCtxFinder = new MqttMsgContextFinder(msg.MessageId, MqttMsgFlow.ToAcknowledge);
                MqttMsgContext       msgCtx       = (MqttMsgContext)clientConnection.InflightQueue.FirstOrDefault(msgCtxFinder.Find);

                // the PUBLISH message is alredy in the inflight queue, we don't need to re-enqueue but we need
                // to change state to re-send PUBREC
                if (msgCtx != null)
                {
                    msgCtx.State = MqttMsgState.QueuedQos2;
                    msgCtx.Flow  = MqttMsgFlow.ToAcknowledge;
                    enqueue      = false;
                }
            }

            if (enqueue)
            {
                // set a default state
                MqttMsgState state = MqttMsgState.QueuedQos0;

                // based on QoS level, the messages flow between broker and client changes
                switch (msg.QosLevel)
                {
                // QoS Level 0
                case MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE:
                    state = MqttMsgState.QueuedQos0;
                    break;

                // QoS Level 1
                case MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE:
                    state = MqttMsgState.QueuedQos1;
                    break;

                // QoS Level 2
                case MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE:
                    state = MqttMsgState.QueuedQos2;
                    break;
                }

                // [v3.1.1] SUBSCRIBE and UNSUBSCRIBE aren't "officially" QOS = 1
                //          so QueuedQos1 state isn't valid for them
                if (msg.Type == MqttMsgBase.MQTT_MSG_SUBSCRIBE_TYPE)
                {
                    state = MqttMsgState.SendSubscribe;
                }
                else if (msg.Type == MqttMsgBase.MQTT_MSG_UNSUBSCRIBE_TYPE)
                {
                    state = MqttMsgState.SendUnsubscribe;
                }

                // queue message context
                MqttMsgContext msgContext = new MqttMsgContext()
                {
                    Message = msg,
                    State   = state,
                    Flow    = flow,
                    Attempt = 0
                };

                // enqueue message and unlock send thread
                clientConnection.EnqueueInflight(msgContext);

                // PUBLISH message
                if (msg.Type == MqttMsgBase.MQTT_MSG_PUBLISH_TYPE)
                {
                    // to publish and QoS level 1 or 2
                    if ((msgContext.Flow == MqttMsgFlow.ToPublish) &&
                        ((msg.QosLevel == MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE) ||
                         (msg.QosLevel == MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE)))
                    {
                        if (clientConnection.Session != null)
                        {
                            clientConnection.Session.InflightMessages.TryAdd(msgContext.Key, msgContext);
                        }
                    }
                    // to acknowledge and QoS level 2
                    else if ((msgContext.Flow == MqttMsgFlow.ToAcknowledge) &&
                             (msg.QosLevel == MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE))
                    {
                        if (clientConnection.Session != null)
                        {
                            clientConnection.Session.InflightMessages.TryAdd(msgContext.Key, msgContext);
                        }
                    }
                }
            }
        }