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); }