Example #1
1
        void Client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
        {
            MqttClient client = (MqttClient)sender;

            if (!mqttBridge.OnPublish(client, e)) return;

            // create PUBLISH message to publish
            // [v3.1.1] DUP flag from an incoming PUBLISH message is not propagated to subscribers
            //          It should be set in the outgoing PUBLISH message based on transmission for each subscriber
            MqttMsgPublish publish = new MqttMsgPublish(e.Topic, e.Message, false, e.QosLevel, e.Retain);

            // publish message through publisher manager
            this.publisherManager.Publish(publish);
        }
Example #2
0
        public static MqttMsgPublish Parse(byte fixedHeaderFirstByte, Socket socket)
        {
            byte[] buffer;
            int    index = 0;

            byte[]         topicUtf8;
            int            topicUtf8Length;
            MqttMsgPublish msg = new MqttMsgPublish();

            // get remaining length and allocate buffer
            int remainingLength = MqttMsgBase.decodeRemainingLength(socket);

            buffer = new byte[remainingLength];

            // read bytes from socket...
            socket.Receive(buffer);

            // topic name
            topicUtf8Length  = ((buffer[index++] << 8) & 0xFF00);
            topicUtf8Length |= buffer[index++];
            topicUtf8        = new byte[topicUtf8Length];
            Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length);
            index    += topicUtf8Length;
            msg.topic = new String(Encoding.UTF8.GetChars(topicUtf8));

            // read QoS level from fixed header
            msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
            // read DUP flag from fixed header
            msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01);
            // read retain flag from fixed header
            msg.retain = (((fixedHeaderFirstByte & RETAIN_FLAG_MASK) >> RETAIN_FLAG_OFFSET) == 0x01);

            // message id is valid only with QOS level 1 or QOS level 2
            if ((msg.qosLevel == QOS_LEVEL_AT_LEAST_ONCE) ||
                (msg.qosLevel == QOS_LEVEL_EXACTLY_ONCE))
            {
                // message id
                msg.messageId  = (ushort)((buffer[index++] << 8) & 0xFF00);
                msg.messageId |= (buffer[index++]);
            }

            // get payload with message data
            msg.message = new byte[remainingLength - index];
            Array.Copy(buffer, index, msg.message, 0, msg.message.Length);

            return(msg);
        }
Example #3
0
 public virtual void PublishToMqttClients(MqttMsgPublish message)
 {
     ((MqttManager)Composable.GetExport<IXSocketController>(typeof(MqttManager))).publisherManager.Publish(message);
 }
        /// <summary>
        /// Parse bytes for a PUBLISH message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>PUBLISH message instance</returns>
        public static MqttMsgPublish Parse(byte fixedHeaderFirstByte, IMqttNetworkChannel channel)
        {
            byte[] buffer;
            int    index = 0;

            byte[]         topicUtf8;
            int            topicUtf8Length;
            MqttMsgPublish msg = new MqttMsgPublish();

            // get remaining length and allocate buffer
            int remainingLength = MqttMsgBase.decodeRemainingLength(channel);

            buffer = new byte[remainingLength];

            // read bytes from socket...
            int received = channel.Receive(buffer);

            // topic name
            topicUtf8Length  = ((buffer[index++] << 8) & 0xFF00);
            topicUtf8Length |= buffer[index++];
            topicUtf8        = new byte[topicUtf8Length];
            Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length);
            index    += topicUtf8Length;
            msg.topic = new String(Encoding.UTF8.GetChars(topicUtf8));

            // read QoS level from fixed header
            msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
            // read DUP flag from fixed header
            msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01);
            // read retain flag from fixed header
            msg.retain = (((fixedHeaderFirstByte & RETAIN_FLAG_MASK) >> RETAIN_FLAG_OFFSET) == 0x01);

            // message id is valid only with QOS level 1 or QOS level 2
            if ((msg.qosLevel == QOS_LEVEL_AT_LEAST_ONCE) ||
                (msg.qosLevel == QOS_LEVEL_EXACTLY_ONCE))
            {
                // message id
                msg.messageId  = (ushort)((buffer[index++] << 8) & 0xFF00);
                msg.messageId |= (buffer[index++]);
            }

            // get payload with message data
            int messageSize   = remainingLength - index;
            int remaining     = messageSize;
            int messageOffset = 0;

            msg.message = new byte[messageSize];

            // BUG FIX 26/07/2013 : receiving large payload

            // copy first part of payload data received
            Array.Copy(buffer, index, msg.message, messageOffset, received - index);
            remaining     -= (received - index);
            messageOffset += (received - index);

            // if payload isn't finished
            while (remaining > 0)
            {
                // receive other payload data
                received = channel.Receive(buffer);
                Array.Copy(buffer, 0, msg.message, messageOffset, received);
                remaining     -= received;
                messageOffset += received;
            }

            return(msg);
        }
Example #5
0
 /// <summary>
 /// Wrapper method for raising PUBLISH message received event
 /// </summary>
 /// <param name="publish">PUBLISH message received</param>
 private void OnMqttMsgPublishReceived(MqttMsgPublish publish)
 {
     if (this.MqttMsgPublishReceived != null)
     {
         this.MqttMsgPublishReceived(this,
             new MqttMsgPublishEventArgs(publish.Topic, publish.Message, publish.QosLevel, publish.Retain));
     }
 }
Example #6
0
        /// <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;
        }
Example #7
0
        /// <summary>
        /// Close a client
        /// </summary>
        /// <param name="client">Client to close</param>
        private void CloseClient(MqttClient client)
        {
            if (this.clients.Contains(client))
            {
                // if client is connected and it has a will message
                if (!client.IsConnected && client.WillFlag)
                {
                    // create the will PUBLISH message
                    MqttMsgPublish publish =
                        new MqttMsgPublish(client.WillTopic, Encoding.UTF8.GetBytes(client.WillMessage), false, client.WillQosLevel, false);

                    // publish message through publisher manager
                    this.publisherManager.Publish(publish);
                }

                // if not clean session
                if (!client.CleanSession)
                {
                    List<MqttSubscription> subscriptions = this.subscriberManager.GetSubscriptionsByClient(client.ClientId);

                    if ((subscriptions != null) && (subscriptions.Count > 0))
                    {
                        this.sessionManager.SaveSession(client.ClientId, client.Session, subscriptions);

                        // TODO : persist client session if broker close
                    }
                }

                // delete client from runtime subscription
                this.subscriberManager.Unsubscribe(client);

                // close the client
                client.Close();

                // remove client from the collection
                this.clients.Remove(client);

                mqttBridge.OnClientDisconnect(client);
            }
        }
Example #8
0
        /// <summary>
        /// Publish a message asynchronously
        /// </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, bool retain)
        {
            MqttMsgPublish publish =
                    new MqttMsgPublish(topic, message, false, qosLevel, retain);
            publish.MessageId = this.GetMessageId();

            // enqueue message to publish into the inflight queue
            this.EnqueueInflight(publish, MqttMsgFlow.ToPublish);           

            return publish.MessageId;
        }
Example #9
0
        public static MqttMsgPublish Parse(byte fixedHeaderFirstByte, Socket socket)
        {
            byte[] buffer;
            int index = 0;
            byte[] topicUtf8;
            int topicUtf8Length;
            MqttMsgPublish msg = new MqttMsgPublish();

            // get remaining length and allocate buffer
            int remainingLength = MqttMsgBase.decodeRemainingLength(socket);
            buffer = new byte[remainingLength];

            // read bytes from socket...
            socket.Receive(buffer);

            // topic name
            topicUtf8Length = ((buffer[index++] << 8) & 0xFF00);
            topicUtf8Length |= buffer[index++];
            topicUtf8 = new byte[topicUtf8Length];
            Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length);
            index += topicUtf8Length;
            msg.topic = new String(Encoding.UTF8.GetChars(topicUtf8));

            // read QoS level from fixed header
            msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
            // read DUP flag from fixed header
            msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01);
            // read retain flag from fixed header
            msg.retain = (((fixedHeaderFirstByte & RETAIN_FLAG_MASK) >> RETAIN_FLAG_OFFSET) == 0x01);

            // message id is valid only with QOS level 1 or QOS level 2
            if ((msg.qosLevel == QOS_LEVEL_AT_LEAST_ONCE) ||
                (msg.qosLevel == QOS_LEVEL_EXACTLY_ONCE))
            {
                // message id
                msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
                msg.messageId |= (buffer[index++]);
            }

            // get payload with message data
            msg.message = new byte[remainingLength - index];
            Array.Copy(buffer, index, msg.message, 0, msg.message.Length);

            return msg;
        }
        /// <summary>
        /// Parse bytes for a PUBLISH message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="protocolVersion">Protocol Version</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>PUBLISH message instance</returns>
        public static MqttMsgPublish Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
        {
            byte[] buffer;
            int index = 0;
            byte[] topicUtf8;
            int topicUtf8Length;
            MqttMsgPublish msg = new MqttMsgPublish();

            // get remaining length and allocate buffer
            int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
            buffer = new byte[remainingLength];

            // read bytes from socket...
            int received = channel.Receive(buffer);

            // topic name
            topicUtf8Length = ((buffer[index++] << 8) & 0xFF00);
            topicUtf8Length |= buffer[index++];
            topicUtf8 = new byte[topicUtf8Length];
            Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length);
            index += topicUtf8Length;
            msg.topic = new String(Encoding.UTF8.GetChars(topicUtf8));

            // read QoS level from fixed header
            msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
            // check wrong QoS level (both bits can't be set 1)
            if (msg.qosLevel > QOS_LEVEL_EXACTLY_ONCE)
                throw new MqttClientException(MqttClientErrorCode.QosNotAllowed);
            // read DUP flag from fixed header
            msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01);
            // read retain flag from fixed header
            msg.retain = (((fixedHeaderFirstByte & RETAIN_FLAG_MASK) >> RETAIN_FLAG_OFFSET) == 0x01);
            
            // message id is valid only with QOS level 1 or QOS level 2
            if ((msg.qosLevel == QOS_LEVEL_AT_LEAST_ONCE) ||
                (msg.qosLevel == QOS_LEVEL_EXACTLY_ONCE))
            {
                // message id
                msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
                msg.messageId |= (buffer[index++]);
            }

            // get payload with message data
            int messageSize = remainingLength - index;
            int remaining = messageSize;
            int messageOffset = 0;
            msg.message = new byte[messageSize];

            // BUG FIX 26/07/2013 : receiving large payload

            // copy first part of payload data received
            Array.Copy(buffer, index, msg.message, messageOffset, received - index);
            remaining -= (received - index);
            messageOffset += (received - index);

            // if payload isn't finished
            while (remaining > 0)
            {
                // receive other payload data
                received = channel.Receive(buffer);
                Array.Copy(buffer, 0, msg.message, messageOffset, received);
                remaining -= received;
                messageOffset += received;
            }

            return msg;
        }
Example #11
0
        /// <summary>
        /// Publish message
        /// </summary>
        /// <param name="publish">Message to publish</param>
        public void Publish(MqttMsgPublish publish)
        {
            if (publish.Retain)
            {
                lock (this.retainedMessages)
                {
                    // retained message already exists for the topic
                    if (retainedMessages.ContainsKey(publish.Topic))
                    {
                        // if empty message, remove current retained message
                        if (publish.Message.Length == 0)
                            retainedMessages.Remove(publish.Topic);
                        // set new retained message for the topic
                        else
                            retainedMessages[publish.Topic] = publish;
                    }
                    else
                    {
                        // add new topic with related retained message
                        retainedMessages.Add(publish.Topic, publish);
                    }
                }
            }

            // enqueue
            lock (this.publishQueue)
            {
                this.publishQueue.Enqueue(publish);
            }

            // unlock thread for sending messages to the subscribers
            this.publishQueueWaitHandle.Set();
        }
Example #12
0
        void Client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
        {
            MqttClient client = (MqttClient)sender;

            // create PUBLISH message to publish
            // [v3.1.1] DUP flag from an incoming PUBLISH message is not propagated to subscribers
            //          It should be set in the outgoing PUBLISH message based on transmission for each subscriber
            MqttMsgPublish publish = new MqttMsgPublish(e.Topic, e.Message, false, e.QosLevel, e.Retain);

            // Authenticate this client can communicate with this topic
            if (this.uacManager.PubSubAuthentication(true, client.ClientId, e.Topic))
            {
                // publish message through publisher manager
                this.publisherManager.Publish(publish);
            }
        }
Example #13
0
        public static MqttMsgPublish Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
        {
            int            num1            = 0;
            MqttMsgPublish mqttMsgPublish1 = new MqttMsgPublish();
            int            length1         = MqttMsgBase.decodeRemainingLength(channel);

            byte[] buffer = new byte[length1];
            int    num2   = channel.Receive(buffer);

            byte[] numArray1 = buffer;
            int    index1    = num1;
            int    num3      = checked (index1 + 1);
            int    num4      = (int)numArray1[index1] << 8 & 65280;

            byte[] numArray2    = buffer;
            int    index2       = num3;
            int    sourceIndex1 = checked (index2 + 1);
            int    num5         = (int)numArray2[index2];
            int    length2      = num4 | num5;

            byte[] bytes = new byte[length2];
            Array.Copy((Array)buffer, sourceIndex1, (Array)bytes, 0, length2);
            int sourceIndex2 = checked (sourceIndex1 + length2);

            mqttMsgPublish1.topic    = new string(Encoding.UTF8.GetChars(bytes));
            mqttMsgPublish1.qosLevel = checked ((byte)(((int)fixedHeaderFirstByte & 6) >> 1));
            if (mqttMsgPublish1.qosLevel > (byte)2)
            {
                throw new MqttClientException(MqttClientErrorCode.QosNotAllowed);
            }
            mqttMsgPublish1.dupFlag = ((int)fixedHeaderFirstByte & 8) >> 3 == 1;
            mqttMsgPublish1.retain  = ((int)fixedHeaderFirstByte & 1) == 1;
            if (mqttMsgPublish1.qosLevel == (byte)1 || mqttMsgPublish1.qosLevel == (byte)2)
            {
                MqttMsgPublish mqttMsgPublish2 = mqttMsgPublish1;
                byte[]         numArray3       = buffer;
                int            index3          = sourceIndex2;
                int            num6            = checked (index3 + 1);
                int            num7            = (int)checked ((ushort)((int)numArray3[index3] << 8 & 65280));
                mqttMsgPublish2.messageId = (ushort)num7;
                MqttMsgPublish mqttMsgPublish3 = mqttMsgPublish1;
                int            messageId       = (int)mqttMsgPublish3.messageId;
                byte[]         numArray4       = buffer;
                int            index4          = num6;
                sourceIndex2 = checked (index4 + 1);
                int num8 = (int)numArray4[index4];
                mqttMsgPublish3.messageId = (ushort)(messageId | num8);
            }
            int length3           = checked (length1 - sourceIndex2);
            int num9              = length3;
            int destinationIndex1 = 0;

            mqttMsgPublish1.message = new byte[length3];
            Array.Copy((Array)buffer, sourceIndex2, (Array)mqttMsgPublish1.message, destinationIndex1, checked (num2 - sourceIndex2));
            int num10             = checked (num9 - num2 - sourceIndex2);
            int destinationIndex2 = checked (destinationIndex1 + num2 - sourceIndex2);

            while (num10 > 0)
            {
                int length4 = channel.Receive(buffer);
                Array.Copy((Array)buffer, 0, (Array)mqttMsgPublish1.message, destinationIndex2, length4);
                checked { num10 -= length4; }
                checked { destinationIndex2 += length4; }
            }
            return(mqttMsgPublish1);
        }