private void RouteOnTheQoSLevelOfTheSubscriber(string topic) { MqttMsgPublish publish = publishQueue[topic].Dequeue(); //var connectedClients = MqttServer.GetConnectedClientIds(); var connectedClients = PacketManager.GetConnectedClientIds(); var subscriptionsByTopic = subscriptionManager.GetSubscriptionsByTopic(publish.Topic); var subscriptions = subscriptionsByTopic != null?subscriptionsByTopic.Where(s => connectedClients.Contains(s.ClientId)) : null; if (subscriptions != null) { foreach (var sub in subscriptions) { if (sub.QosLevel == 0x00 && publish.QosLevel > MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE) { MqttMsgPublish pub = MqttMsgPublish.Parse(publish.GetBytes()); pub.QosLevel = MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE; RouteOnQoS(pub, sub); } else if (sub.QosLevel == 0x01 && publish.QosLevel > MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE) { MqttMsgPublish pub = MqttMsgPublish.Parse(publish.GetBytes()); pub.QosLevel = MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE; RouteOnQoS(pub, sub); } else { RouteOnQoS(publish, sub); } } } }
/// <summary> /// Delivers to the subscribers with qos 0 of the publish topic the publish message /// </summary> /// <param name="sender"></param> /// <param name="publish"></param> private void ManageQoS0(MqttMsgPublish publish, Subscription subscription) { try { //MqttServer.Instance.Send(subscription.ClientId, publish.GetBytes()); OnPacketReadyToBeSent(subscription.ClientId, publish.GetBytes()); } catch (Exception) { throw; } }
/// <summary> /// Publish a message to the broker /// </summary> /// <param name="topic">Message topic</param> /// <param name="message">Message data (payload)</param> /// <param name="qosLevel">QoS Level</param> /// <param name="retain">Retain flag</param> /// <returns>Message Id related to PUBLISH message</returns> public ushort Publish(string topic, byte[] message, byte qosLevel = MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE, bool retain = false) { ushort messageId = 0; int attempts = 0; bool acknowledged = false; MqttMsgPublish publish = new MqttMsgPublish(topic, message, false, qosLevel, retain); // based on QoS level, the messages flow between client and broker changes switch (qosLevel) { // QoS Level 0, no answer from broker case MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE: this.Send(publish.GetBytes()); break; // QoS Level 1, waiting for PUBACK message from broker case MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE: attempts = 0; acknowledged = false; do { MqttMsgPuback puback = null; try { // try publish puback = (MqttMsgPuback)this.SendReceive(publish.GetBytes()); acknowledged = true; } catch (MqttTimeoutException) { // no PUBACK message received in time, retry with duplicate flag attempts++; publish.DupFlag = true; // delay before retry if (attempts < MQTT_ATTEMPTS_RETRY) { Thread.Sleep(MQTT_DELAY_RETRY); } } } while ((attempts < MQTT_ATTEMPTS_RETRY) && !acknowledged); if (acknowledged) { messageId = publish.MessageId; } break; // QoS Level 2, waiting for PUBREC message from broker, // send PUBREL message and waiting for PUBCOMP message from broker case MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE: attempts = 0; acknowledged = false; do { MqttMsgPubrec pubrec = null; try { // try publish pubrec = (MqttMsgPubrec)this.SendReceive(publish.GetBytes()); acknowledged = true; } catch (MqttTimeoutException) { // no PUBREC message received in time, retry with duplicate flag attempts++; publish.DupFlag = true; // delay before retry if (attempts < MQTT_ATTEMPTS_RETRY) { Thread.Sleep(MQTT_DELAY_RETRY); } } } while ((attempts < MQTT_ATTEMPTS_RETRY) && !acknowledged); // first phase ok if (acknowledged) { attempts = 0; acknowledged = false; do { // set publish message identifier into PUBREL message MqttMsgPubrel pubrel = new MqttMsgPubrel(); pubrel.MessageId = publish.MessageId; MqttMsgPubcomp pubcomp = null; try { // try send PUBREL message pubcomp = (MqttMsgPubcomp)this.SendReceive(pubrel.GetBytes()); acknowledged = true; } catch (MqttTimeoutException) { // no PUBCOMP message received in time, retry with duplicate flag attempts++; pubrel.DupFlag = true; // delay before retry if (attempts < MQTT_ATTEMPTS_RETRY) { Thread.Sleep(MQTT_DELAY_RETRY); } } } while ((attempts < MQTT_ATTEMPTS_RETRY) && !acknowledged); if (acknowledged) { messageId = publish.MessageId; } } break; default: throw new MqttClientException(MqttClientErrorCode.QosNotAllowed); } return(messageId); }