예제 #1
0
        /// <summary>
        ///     Handles the publish complete, for messages that are undergoing Qos ExactlyOnce processing.
        /// </summary>
        /// <param name="msg">The MSG.</param>
        /// <returns>Boolean value indicating whether the message was successfull processed.</returns>
        private bool HandlePublishRelease(MqttMessage msg)
        {
            var pubRelMsg      = (MqttPublishReleaseMessage)msg;
            var publishSuccess = true;

            try {
                MqttPublishMessage pubMsg;
                receivedMessages.TryGetValue(pubRelMsg.VariableHeader.MessageIdentifier, out pubMsg);
                if (pubMsg != null)
                {
                    receivedMessages.Remove(pubRelMsg.VariableHeader.MessageIdentifier);

                    // send the message for processing to whoever is waiting.
                    var topic = new PublicationTopic(pubMsg.VariableHeader.TopicName);
                    OnMessageReceived(topic, pubMsg);

                    var compMsg = new MqttPublishCompleteMessage()
                                  .WithMessageIdentifier(pubMsg.VariableHeader.MessageIdentifier);
                    connectionHandler.SendMessage(compMsg);
                }
            } catch (ArgumentException ex) {
                Log.Warn(m => m("Message recieved which contained topic ({0}) that was not valid according to MQTT Spec was suppressed.",
                                pubRelMsg.VariableHeader.TopicName), ex);
                publishSuccess = false;
            } catch (Exception ex) {
                Log.Error(m => m("An error occurred while processing a publish release message received from a broker ({0}).", msg), ex);
                publishSuccess = false;
            }

            return(publishSuccess);
        }
예제 #2
0
        /// <summary>
        /// Raises the MessageReceived event.
        /// </summary>
        /// <param name="topic">The topic the message belongs to.</param>
        /// <param name="msg">The message received.</param>
        private void OnMessageReceived(PublicationTopic topic, MqttPublishMessage msg)
        {
            var handler = MessageReceived;

            if (handler != null)
            {
                handler(this, new PublishEventArgs(topic, msg));
            }
        }
예제 #3
0
        // ReSharper restore NotResolvedInText

        /// <summary>
        ///     Checks if the rawTopic matches the supplied rawTopic using the MQTT rawTopic matching rules.
        /// </summary>
        /// <param name="matcheeTopic">The rawTopic to match.</param>
        /// <returns>True if the rawTopic matches based on the MQTT rawTopic matching rules, otherwise false.</returns>
        public bool Matches(PublicationTopic matcheeTopic)
        {
            // of the left rawTopic is just a multi wildcard then we have a match without
            // needing to check any further.
            if (this.RawTopic.Equals(MultiWildcard))
            {
                return(true);
            }
            // if the topics are an exact match, bail early with a cheap comparison
            if (Equals(matcheeTopic))
            {
                return(true);
            }
            // no match yet so we need to check each fragment
            for (var i = 0; i < this.TopicFragments.Length; i++)
            {
                var lhsFragment = TopicFragments[i];
                // if we've reached a multi wildcard in the lhs rawTopic,
                // we have a match.
                // (this is the mqtt spec rule finance matches finance or finance/#)
                if (lhsFragment.Equals(MultiWildcard))
                {
                    return(true);
                }
                var isLhsWildcard = lhsFragment.Equals(Wildcard);
                // if we've reached a wildcard match but the matchee does not have anything at
                // this fragment level then it's not a match.
                // (this is the mqtt spec rule finance does not match finance/+
                if (isLhsWildcard && matcheeTopic.TopicFragments.Length <= i)
                {
                    return(false);
                }
                // if lhs is not a wildcard we need to check whether the
                // two fragments match each other.
                if (!isLhsWildcard)
                {
                    var rhsFragment = matcheeTopic.TopicFragments[i];
                    // if lhs fragment is not wildcard then we need an exact match
                    if (!lhsFragment.Equals(rhsFragment))
                    {
                        return(false);
                    }
                }
                // if we're at the last fragment of the lhs rawTopic but there are
                // more fragments in the in the matchee then the matchee rawTopic
                // is too specific to be a match.
                if (i + 1 == this.TopicFragments.Length &&
                    matcheeTopic.TopicFragments.Length > this.TopicFragments.Length)
                {
                    return(false);
                }
                // if we're here the current fragment matches so check the next
            }
            // if we exit out of the loop without a return then we have a full match rawTopic/rawTopic which would
            // have been caught by the original exact match check at the top anyway.
            return(true);
        }
예제 #4
0
        /// <summary>
        ///     Handles the receipt of publish messages from a message broker.
        /// </summary>
        /// <param name="msg">The message that was published.</param>
        /// <returns></returns>
        private bool HandlePublish(MqttMessage msg)
        {
            var pubMsg         = (MqttPublishMessage)msg;
            var publishSuccess = true;

            try {
                var topic = new PublicationTopic(pubMsg.VariableHeader.TopicName);
                if (pubMsg.Header.Qos == MqttQos.AtMostOnce)
                {
                    // QOS AtMostOnce 0 require no response.

                    // send the message for processing to whoever is waiting.
                    OnMessageReceived(topic, pubMsg);
                }
                else if (pubMsg.Header.Qos == MqttQos.AtLeastOnce)
                {
                    // QOS AtLeastOnce 1 require an acknowledgement

                    // send the message for processing to whoever is waiting.
                    OnMessageReceived(topic, pubMsg);

                    var ackMsg = new MqttPublishAckMessage()
                                 .WithMessageIdentifier(pubMsg.VariableHeader.MessageIdentifier);
                    connectionHandler.SendMessage(ackMsg);
                }
                else if (pubMsg.Header.Qos == MqttQos.ExactlyOnce)
                {
                    // QOS ExactlyOnce means we can't give it away yet, we gotta do a handshake
                    // to make sure the broker knows we got it, and we know he knows we got it.

                    // if we've already got it thats ok, it just means its being republished because
                    // of a handshake breakdown, overwrite our existing one for the sake of it
                    if (!receivedMessages.ContainsKey(pubMsg.VariableHeader.MessageIdentifier))
                    {
                        receivedMessages[pubMsg.VariableHeader.MessageIdentifier] = pubMsg;
                    }

                    var pubRecv = new MqttPublishReceivedMessage()
                                  .WithMessageIdentifier(pubMsg.VariableHeader.MessageIdentifier);
                    connectionHandler.SendMessage(pubRecv);
                }
            } catch (ArgumentException ex) {
                Log.Warn(m => m("Message recieved which contained topic ({0}) that was not valid according to MQTT Spec was suppressed.",
                                pubMsg.VariableHeader.TopicName), ex);
                publishSuccess = false;
            } catch (Exception ex) {
                Log.Error(m => m("An error occurred while processing a message received from a broker ({0}).", msg), ex);
                publishSuccess = false;
            }
            return(publishSuccess);
        }
예제 #5
0
        /// <summary>
        ///     Publishes a message to the message broker.
        /// </summary>
        /// <typeparam name="TPayloadConverter">The type of the data converter to use.</typeparam>
        /// <typeparam name="T">The Type of the data being published</typeparam>
        /// <param name="topic">The topic to publish the message to.</param>
        /// <param name="qualityOfService">The quality of service to attach to the message.</param>
        /// <param name="data">The message to publish.</param>
        /// <returns>
        ///     The message identiier assigned to the message.
        /// </returns>
        /// <exception cref="InvalidTopicException">Thrown if the topic supplied violates the MQTT topic format rules.</exception>
        public short PublishMessage <T, TPayloadConverter>(string topic, MqttQos qualityOfService, T data)
            where TPayloadConverter : IPayloadConverter <T>, new()
        {
            if (connectionHandler.State != ConnectionState.Connected)
            {
                throw new ConnectionException(connectionHandler.State);
            }

            try {
                var pubTopic = new PublicationTopic(topic);
                return(publishingManager.Publish <T, TPayloadConverter>(pubTopic, qualityOfService, data));
            } catch (ArgumentException ex) {
                throw new InvalidTopicException(ex.Message, topic, ex);
            }
        }
예제 #6
0
        // ReSharper restore NotResolvedInText

        /// <summary>
        ///     Checks if the rawTopic matches the supplied rawTopic using the MQTT rawTopic matching rules.
        /// </summary>
        /// <param name="matcheeTopic">The rawTopic to match.</param>
        /// <returns>True if the rawTopic matches based on the MQTT rawTopic matching rules, otherwise false.</returns>
        public bool Matches(PublicationTopic matcheeTopic) {
            // of the left rawTopic is just a multi wildcard then we have a match without
            // needing to check any further.
            if (this.RawTopic.Equals(MultiWildcard)) {
                return true;
            }
            // if the topics are an exact match, bail early with a cheap comparison
            if (Equals(matcheeTopic)) {
                return true;
            }
            // no match yet so we need to check each fragment
            for (var i = 0; i < this.TopicFragments.Length; i++) {
                var lhsFragment = TopicFragments[i];
                // if we've reached a multi wildcard in the lhs rawTopic, 
                // we have a match. 
                // (this is the mqtt spec rule finance matches finance or finance/#)
                if (lhsFragment.Equals(MultiWildcard)) {
                    return true;
                }
                var isLhsWildcard = lhsFragment.Equals(Wildcard);
                // if we've reached a wildcard match but the matchee does not have anything at
                // this fragment level then it's not a match. 
                // (this is the mqtt spec rule finance does not match finance/+
                if (isLhsWildcard && matcheeTopic.TopicFragments.Length <= i) {
                    return false;
                }
                // if lhs is not a wildcard we need to check whether the
                // two fragments match each other.
                if (!isLhsWildcard) {
                    var rhsFragment = matcheeTopic.TopicFragments[i];
                    // if lhs fragment is not wildcard then we need an exact match 
                    if (!lhsFragment.Equals(rhsFragment)) {
                        return false;
                    }
                }
                // if we're at the last fragment of the lhs rawTopic but there are
                // more fragments in the in the matchee then the matchee rawTopic
                // is too specific to be a match.
                if (i + 1 == this.TopicFragments.Length &&
                    matcheeTopic.TopicFragments.Length > this.TopicFragments.Length) {
                    return false;
                }
                // if we're here the current fragment matches so check the next
            }
            // if we exit out of the loop without a return then we have a full match rawTopic/rawTopic which would
            // have been caught by the original exact match check at the top anyway.
            return true;
        }
예제 #7
0
        /// <summary>
        ///     Publish a message to the broker on the specified topic.
        /// </summary>
        /// <param name="topic">The topic to send the message to.</param>
        /// <param name="qualityOfService">The QOS to use when publishing the message.</param>
        /// <param name="data">The message to send.</param>
        /// <returns>The message identifier assigned to the message.</returns>
        public short Publish <T, TPayloadConverter>(PublicationTopic topic, MqttQos qualityOfService, T data)
            where TPayloadConverter : IPayloadConverter <T>, new()
        {
            var msgId = messageIdentifierDispenser.GetNextMessageIdentifier(String.Format("topic:{0}", topic));

            Log.DebugFormat("Publishing message ID {0} on topic {1} using QOS {2}", msgId, topic, qualityOfService);

            var converter = GetPayloadConverter <TPayloadConverter>();
            var msg       = new MqttPublishMessage()
                            .ToTopic(topic.ToString())
                            .WithMessageIdentifier(msgId)
                            .WithQos(qualityOfService)
                            .PublishData(converter.ConvertToBytes(data));

            // QOS level 1 or 2 messages need to be saved so we can do the ack processes
            if (qualityOfService == MqttQos.AtLeastOnce || qualityOfService == MqttQos.ExactlyOnce)
            {
                publishedMessages.Add(msgId, msg);
            }

            connectionHandler.SendMessage(msg);
            return(msgId);
        }
예제 #8
0
 /// <summary>
 /// Creates a new instance of a PublishEventArgs class.
 /// </summary>
 /// <param name="topic">The parsed topic.</param>
 /// <param name="publishMessage">The MQTT Publish Message that's been published.</param>
 public PublishEventArgs(PublicationTopic topic, MqttPublishMessage publishMessage)
 {
     Topic          = topic;
     PublishMessage = publishMessage;
 }
예제 #9
0
 /// <summary>
 /// Creates a new instance of a PublishEventArgs class.
 /// </summary>
 /// <param name="topic">The parsed topic.</param>
 /// <param name="publishMessage">The MQTT Publish Message that's been published.</param>
 public PublishEventArgs(PublicationTopic topic, MqttPublishMessage publishMessage) {
     Topic          = topic;
     PublishMessage = publishMessage;
 }