Esempio n. 1
0
 public void EnqueueInflightCallback(InflightQueueProcessEvent processEvent)
 {
     if (this.ConnectionManager != null)
     {
         this.ConnectionManager.EnqueueClientConnectionWithInflightQueueToProcess(processEvent);
     }
 }
        public static void ProcessInflightQueue(InflightQueueProcessEvent processEvent)
        {
            var clientConnection = processEvent.ClientConnection;

            if (!clientConnection.IsRunning)
            {
                return;
            }

            // Check if queue has been processed since callback was created
            if (processEvent.IsCallback && clientConnection.InflightQueueLastProcessedTime != processEvent.CallbackCreationTime)
            {
                return;
            }

            MqttMsgBase msgReceived          = null;
            bool        msgReceivedProcessed = false;
            int         timeout = int.MaxValue;

            // a message inflight could be re-enqueued but we have to
            // analyze it only just one time for cycle
            int count = clientConnection.InflightQueue.Count;

            while (count > 0 && clientConnection.IsRunning)
            {
                count--;
                msgReceived = null;

                // dequeue message context from queue
                MqttMsgContext msgContext;
                if (!clientConnection.InflightQueue.TryDequeue(out msgContext))
                {
                    break;
                }

                // get inflight message
                var msgInflight = (MqttMsgBase)msgContext.Message;

                switch (msgContext.State)
                {
                case MqttMsgState.QueuedQos0:
                    HandleQueuedQos0(clientConnection, msgContext, msgInflight);
                    break;

                // [v3.1.1] SUBSCRIBE and UNSIBSCRIBE aren't "officially" QOS = 1
                case MqttMsgState.QueuedQos1:
                case MqttMsgState.SendSubscribe:
                case MqttMsgState.SendUnsubscribe:
                    timeout = HandleQueuedQos1SendSubscribeAndSendUnsubscribe(clientConnection, msgContext, msgInflight, timeout);
                    break;

                case MqttMsgState.QueuedQos2:
                    timeout = HandleQueuedQos2(clientConnection, msgContext, msgInflight, timeout);
                    break;

                case MqttMsgState.WaitForPuback:
                case MqttMsgState.WaitForSuback:
                case MqttMsgState.WaitForUnsuback:
                    msgReceived = HandleWaitForPubackSubackUbsuback(clientConnection, msgContext, msgInflight, ref msgReceivedProcessed, ref timeout);
                    break;

                case MqttMsgState.WaitForPubrec:
                    msgReceived = HandleWaitForPubrec(clientConnection, msgContext, msgInflight, ref msgReceivedProcessed, ref timeout);
                    break;

                case MqttMsgState.WaitForPubrel:
                    msgReceived = WaitForPubrel(clientConnection, msgContext, msgInflight, ref msgReceivedProcessed);
                    break;

                case MqttMsgState.WaitForPubcomp:
                    msgReceived = WaitForPubcomp(clientConnection, msgContext, msgInflight, ref msgReceivedProcessed, ref timeout);
                    break;

                case MqttMsgState.SendPubrec:
                    // TODO : impossible ? --> QueuedQos2 ToAcknowledge
                    break;

                case MqttMsgState.SendPubrel:
                    timeout = SendPubrel(clientConnection, msgContext, msgInflight, timeout);
                    break;

                case MqttMsgState.SendPubcomp:
                    // TODO : impossible ?
                    break;

                case MqttMsgState.SendPuback:
                    // TODO : impossible ? --> QueuedQos1 ToAcknowledge
                    break;

                default:
                    break;
                }
            }

            // if message received is orphan, no corresponding message in inflight queue
            // based on messageId, we need to remove from the queue
            if ((msgReceived != null) && !msgReceivedProcessed)
            {
                MqttMsgBase dequeuedMsg;
                clientConnection.InternalQueue.TryDequeue(out dequeuedMsg);
            }

            clientConnection.InflightQueueLastProcessedTime = Environment.TickCount;
            if (!clientConnection.InflightQueue.IsEmpty)
            {
                var inflightQueueProcessEvent = new InflightQueueProcessEvent {
                    ClientConnection = clientConnection, IsCallback = true, CallbackCreationTime = timeout
                };
                Task.Factory.StartNew(() => SetTimer(inflightQueueProcessEvent, timeout));
            }
        }
        private static async void SetTimer(InflightQueueProcessEvent processEvent, int timeout)
        {
            await Task.Delay(timeout);

            processEvent.ClientConnection.EnqueueInflightCallback(processEvent);
        }
 public void EnqueueClientConnectionWithInflightQueueToProcess(InflightQueueProcessEvent processEvent)
 {
     clientConnectionsWithInflightQueuesToProcess.Add(processEvent);
 }