Пример #1
0
        private void Publish(MqttQualityOfService QoS)
        {
            ManualResetEvent Done  = new ManualResetEvent(false);
            ManualResetEvent Error = new ManualResetEvent(false);

            this.Test_01_Connect();

            this.client.OnContentReceived += (sender, e) =>
            {
                string s = System.Text.Encoding.UTF8.GetString(e.Data);

                if (s == "Hello world.")
                {
                    Done.Set();
                }
                else
                {
                    Error.Set();
                }
            };

            this.client.SUBSCRIBE("/Waher/IoT/Test", QoS);
            try
            {
                this.client.PUBLISH("/Waher/IoT/Test", QoS, false,
                                    System.Text.Encoding.UTF8.GetBytes("Hello world."));

                Assert.AreEqual(0, WaitHandle.WaitAny(new WaitHandle[] { Done, Error }, 10000), "Content not published correctly.");
            }
            finally
            {
                this.client.UNSUBSCRIBE("/Waher/IoT/Test");
            }
        }
Пример #2
0
        /// <summary>
        /// Sets properties and attributes of class in accordance with XML definition.
        /// </summary>
        /// <param name="Definition">XML definition</param>
        public override Task FromXml(XmlElement Definition)
        {
            this.topic = XML.Attribute(Definition, "topic");
            this.qos   = (MqttQualityOfService)XML.Attribute(Definition, "qos", MqttQualityOfService.AtMostOnce);

            return(Task.CompletedTask);
        }
Пример #3
0
 protected PubSubAttribute(string topic, MqttQualityOfService qoS, string logger, MqttQualityOfService loggerQoS)
 {
     Topic     = topic;
     QoS       = qoS;
     LoggerQoS = loggerQoS;
     Logger    = logger;
 }
        IEnumerable <Subscription> GetSubscriptions(byte[] bytes, int headerLength)
        {
            if (bytes.Length - headerLength < 4)  //At least 4 bytes required on payload: MSB, LSB, Topic Filter, Requests QoS
            {
                throw new MqttProtocolViolationException(ClientProperties.SubscribeFormatter_MissingTopicFilterQosPair);
            }

            int index = headerLength;

            do
            {
                string topicFilter = bytes.GetString(index, out index);

                if (!topicEvaluator.IsValidTopicFilter(topicFilter))
                {
                    throw new MqttException(ClientProperties.SubscribeFormatter_InvalidTopicFilter(topicFilter));
                }

                byte requestedQosByte = bytes.Byte(index);

                if (!Enum.IsDefined(typeof(MqttQualityOfService), requestedQosByte))
                {
                    throw new MqttProtocolViolationException(ClientProperties.Formatter_InvalidQualityOfService);
                }

                MqttQualityOfService requestedQos = (MqttQualityOfService)requestedQosByte;

                yield return(new Subscription(topicFilter, requestedQos));

                index++;
            } while(bytes.Length - index + 1 >= 2);
        }
Пример #5
0
        public async Task PublishAsync(MqttApplicationMessage message, MqttQualityOfService qos, bool retain = false)
        {
            if (disposed)
            {
                throw new ObjectDisposedException(GetType().FullName);
            }

            try {
                ushort?packetId = qos == MqttQualityOfService.AtMostOnce ? null : (ushort?)packetIdProvider.GetPacketId();
                var    publish  = new Publish(message.Topic, qos, retain, duplicated: false, packetId: packetId)
                {
                    Payload = message.Payload
                };

                var senderFlow = flowProvider.GetFlow <PublishSenderFlow> ();

                await clientSender.Run(async() => {
                    await senderFlow.SendPublishAsync(Id, publish, Channel)
                    .ConfigureAwait(continueOnCapturedContext: false);
                }).ConfigureAwait(continueOnCapturedContext: false);
            } catch (Exception ex) {
                Close(ex);
                throw;
            }
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="MqttLastWill" /> class,
 /// specifying the topic to pusblish the last will message to, the Quality of Service (QoS)
 /// to use, if the message should be sent as a retained message and also the content of the will message
 /// to publish
 /// </summary>
 /// <param name="topic">Topic to publish the last will message to</param>
 /// <param name="qualityOfService">
 /// Quality of Service (QoS) to use when publishing the last will message.
 /// See <see cref="MqttQualityOfService" /> for more details about the QoS meanings
 /// </param>
 /// <param name="retain">Specifies if the message should be retained or not</param>
 /// <param name="payload">Payload of the will message to publish</param>
 public MqttLastWill(string topic, MqttQualityOfService qualityOfService, bool retain, byte[] payload)
 {
     Topic            = topic;
     QualityOfService = qualityOfService;
     Retain           = retain;
     Payload          = payload;
 }
        public async Task SendPublishAsync(string clientId, Publish message, IMqttChannel <IPacket> channel, PendingMessageStatus status = PendingMessageStatus.PendingToSend)
        {
            if (channel == null || !channel.IsConnected)
            {
                SaveMessage(message, clientId, PendingMessageStatus.PendingToSend);
                return;
            }

            MqttQualityOfService qos = configuration.GetSupportedQos(message.QualityOfService);

            if (qos != MqttQualityOfService.AtMostOnce && status == PendingMessageStatus.PendingToSend)
            {
                SaveMessage(message, clientId, PendingMessageStatus.PendingToAcknowledge);
            }

            await channel.SendAsync(message);

            if (qos == MqttQualityOfService.AtLeastOnce)
            {
                await MonitorAckAsync <PublishAck>(message, clientId, channel);
            }
            else if (qos == MqttQualityOfService.ExactlyOnce)
            {
                await MonitorAckAsync <PublishReceived>(message, clientId, channel);

                await channel
                .ReceiverStream
                .ObserveOn(NewThreadScheduler.Default)
                .OfType <PublishComplete>()
                .FirstOrDefaultAsync(x => x.PacketId == message.PacketId.Value);
            }
        }
Пример #8
0
 /// <summary>
 /// Initializes a new instance of the <see cref="MqttLastWill" /> class,
 /// specifying the topic to pusblish the last will message to, the Quality of Service (QoS)
 /// to use, if the message should be sent as a retained message and also the content of the will message
 /// to publish
 /// </summary>
 /// <param name="topic">Topic to publish the last will message to</param>
 /// <param name="qualityOfService">
 /// Quality of Service (QoS) to use when publishing the last will message.
 /// See <see cref="MqttQualityOfService" /> for more details about the QoS meanings
 /// </param>
 /// <param name="retain">Specifies if the message should be retained or not</param>
 /// <param name="message">Content of the will message to publish</param>
 public MqttLastWill(string topic, MqttQualityOfService qualityOfService, bool retain, string message)
 {
     Topic            = topic;
     QualityOfService = qualityOfService;
     Retain           = retain;
     Message          = message;
 }
Пример #9
0
        /// <summary>
        /// Subscribe an action to a topic
        /// </summary>
        /// <param name="topic"></param>
        /// <param name="action"></param>
        /// <param name="qoS"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public Guid SubscribeToTopic <T>(string topic, Action <T> action,
                                         MqttQualityOfService qoS = MqttQualityOfService.ExactlyOnce) where T : class, new()
        {
            // Create a new id for the action
            var guid = Guid.NewGuid();
            var id   = guid.ToString();

            // Helper variables to assess topics with wildcards correctly
            Func <string, string, bool> condition;
            string sanitizedTopic;

            // Does the topic contain a wildcard?
            if (_containsWildcards(topic))
            {
                // Convert the mqtt wildcards with proper regex terms
                sanitizedTopic = _replaceWildCards(topic);
                // To compare those terms use the Regex.IsMatch functionality
                condition = Regex.IsMatch;
            }
            else
            {
                // If the topic does not contain any mqtt wildcards, than it can stay as it is
                sanitizedTopic = topic;
                // To compare the topics, use regular string comparision
                condition = (key, topic) => key.Equals(topic);
            }

            // If there was not prior subscription to that topic, subscribe for that topic at the mqtt message broker
            if (!_consumers.Keys.Any(key => condition(key, sanitizedTopic)))
            {
                _bus.SubscribeAsync(sanitizedTopic, qoS);
            }

            // Get the list of actions that belong to that topic
            if (!_consumers.Keys.Any(key => condition(key, sanitizedTopic)))
            {
                _consumers[sanitizedTopic] = new Dictionary <string, Action <byte[]> >();
            }

            // Add the new action
            // The action of the caller is wrapped in an action that does the casting of the message
            _consumers[sanitizedTopic][id] = bytes =>
            {
                T message = null;
                try
                {
                    var jsonString = Utf8Encoding.GetString(bytes);
                    message = JsonConvert.DeserializeObject <T>(jsonString);
                }
                catch (Exception e)
                {
                    // ignore
                }

                // Execute the callers action with the message as parameter
                action(message);
            };

            return(guid);
        }
Пример #10
0
        /// <summary>
        /// Manages an MQTT connection. Implements MQTT v3.1.1, as defined in
        /// http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html
        /// </summary>
        /// <param name="Host">Host name or IP address of MQTT server.</param>
        /// <param name="Port">Port to connect to.</param>
        /// <param name="Tls">If TLS is used to encrypt communication.</param>
        /// <param name="UserName">User Name</param>
        /// <param name="Password">Password</param>
        /// <param name="WillTopic">Topic to publish the last will and testament, in case the connection drops unexpectedly.</param>
        /// <param name="WillQoS">Quality of Service of last will and testament, in case the connection drops unexpectedly.</param>
        /// <param name="WillRetain">If last will and testament should be retained, in case the connection drops unexpectedly.</param>
        /// <param name="WillData">Data of last will and testament, in case the connection drops unexpectedly.</param>
        /// <param name="Sniffers">Sniffers to use.</param>
        public MqttClient(string Host, int Port, bool Tls, string UserName, string Password, string WillTopic,
                          MqttQualityOfService WillQoS, bool WillRetain, byte[] WillData, params ISniffer[] Sniffers)
            : base(Sniffers)
        {
            this.host     = Host;
            this.port     = Port;
            this.tls      = Tls;
            this.userName = UserName;
            this.password = Password;
#if !WINDOWS_UWP
            this.clientCertificate = null;
#endif
            this.state      = MqttState.Offline;
            this.will       = !string.IsNullOrEmpty(WillTopic) && WillData != null;
            this.willTopic  = WillTopic;
            this.willQoS    = WillQoS;
            this.willRetain = WillRetain;
            this.willData   = WillData;

            if (this.will && this.willData.Length > 65535)
            {
                throw new ArgumentException("Will data too large.", nameof(WillData));
            }

            Task.Run(() => this.BeginConnect());
        }
Пример #11
0
        /// <summary>
        /// Publish a message to the mqtt message broker.
        /// </summary>
        /// <param name="topic"></param>
        /// <param name="message"></param>
        /// <param name="qoS"></param>
        /// <typeparam name="T"></typeparam>
        public void Publish <T>(string topic, T message, MqttQualityOfService qoS = MqttQualityOfService.ExactlyOnce)
            where T : class
        {
            var jsonString         = JsonConvert.SerializeObject(message);
            var applicationMessage = new MqttApplicationMessage(topic, Utf8Encoding.GetBytes(jsonString));

            _bus.PublishAsync(applicationMessage, qoS);
        }
Пример #12
0
 public Publish(string topic, MqttQualityOfService qualityOfService, bool retain, bool duplicated, ushort?packetId = null)
 {
     QualityOfService = qualityOfService;
     Duplicated       = duplicated;
     Retain           = retain;
     Topic            = topic;
     PacketId         = packetId;
 }
Пример #13
0
        public async Task SubscribeAsync(string topicFilter, MqttQualityOfService qos)
        {
            if (disposed)
            {
                throw new ObjectDisposedException(GetType().FullName);
            }

            try {
                var packetId  = packetIdProvider.GetPacketId();
                var subscribe = new Subscribe(packetId, new Subscription(topicFilter, qos));

                var ack = default(SubscribeAck);
                var subscribeTimeout = TimeSpan.FromSeconds(configuration.WaitTimeoutSecs);

                await SendPacketAsync(subscribe)
                .ConfigureAwait(continueOnCapturedContext: false);

                ack = await packetListener
                      .PacketStream
                      .ObserveOn(NewThreadScheduler.Default)
                      .OfType <SubscribeAck> ()
                      .FirstOrDefaultAsync(x => x.PacketId == packetId)
                      .Timeout(subscribeTimeout);

                if (ack == null)
                {
                    var message = string.Format(Properties.Resources.Client_SubscriptionDisconnected, Id, topicFilter);

                    tracer.Error(message);

                    throw new MqttClientException(message);
                }

                if (ack.ReturnCodes.FirstOrDefault() == SubscribeReturnCode.Failure)
                {
                    var message = string.Format(Properties.Resources.Client_SubscriptionRejected, Id, topicFilter);

                    tracer.Error(message);

                    throw new MqttClientException(message);
                }
            } catch (TimeoutException timeEx) {
                Close(timeEx);

                var message = string.Format(Properties.Resources.Client_SubscribeTimeout, Id, topicFilter);

                throw new MqttClientException(message, timeEx);
            } catch (MqttClientException clientEx) {
                Close(clientEx);
                throw;
            } catch (Exception ex) {
                Close(ex);

                var message = string.Format(Properties.Resources.Client_SubscribeError, Id, topicFilter);

                throw new MqttClientException(message, ex);
            }
        }
        public async Task when_subscribing_topic_with_retain_message_then_retained_is_sent()
        {
            MqttConfiguration configuration = new MqttConfiguration {
                MaximumQualityOfService = MqttQualityOfService.AtLeastOnce
            };
            Mock <IMqttTopicEvaluator>          topicEvaluator    = new Mock <IMqttTopicEvaluator>();
            Mock <IRepository <ClientSession> > sessionRepository = new Mock <IRepository <ClientSession> >();
            IPacketIdProvider packetIdProvider = Mock.Of <IPacketIdProvider>();
            Mock <IRepository <RetainedMessage> > retainedMessageRepository = new Mock <IRepository <RetainedMessage> >();
            Mock <IPublishSenderFlow>             senderFlow = new Mock <IPublishSenderFlow>();

            string        clientId = Guid.NewGuid().ToString();
            ClientSession session  = new ClientSession(clientId, clean: false);

            sessionRepository.Setup(r => r.Read(It.IsAny <string>())).Returns(session);

            MqttQualityOfService fooQoS  = MqttQualityOfService.AtLeastOnce;
            string       fooTopic        = "test/foo/#";
            Subscription fooSubscription = new Subscription(fooTopic, fooQoS);

            string retainedTopic             = "test/foo/bar";
            MqttQualityOfService retainedQoS = MqttQualityOfService.ExactlyOnce;

            byte[] retainedPayload = Encoding.UTF8.GetBytes("Retained Message Test");
            List <RetainedMessage> retainedMessages = new List <RetainedMessage> {
                new RetainedMessage(retainedTopic, retainedQoS, retainedPayload)
            };

            topicEvaluator.Setup(e => e.IsValidTopicFilter(It.IsAny <string>())).Returns(true);
            topicEvaluator.Setup(e => e.Matches(It.IsAny <string>(), It.IsAny <string>())).Returns(true);
            retainedMessageRepository.Setup(r => r.ReadAll()).Returns(retainedMessages.AsQueryable());

            ushort    packetId  = (ushort)new Random().Next(0, ushort.MaxValue);
            Subscribe subscribe = new Subscribe(packetId, fooSubscription);

            Mock <IMqttChannel <IPacket> > channel = new Mock <IMqttChannel <IPacket> >();

            Mock <IConnectionProvider> connectionProvider = new Mock <IConnectionProvider>();

            connectionProvider
            .Setup(p => p.GetConnection(It.Is <string>(c => c == clientId)))
            .Returns(channel.Object);

            ServerSubscribeFlow flow = new ServerSubscribeFlow(topicEvaluator.Object,
                                                               sessionRepository.Object, retainedMessageRepository.Object,
                                                               packetIdProvider, senderFlow.Object, configuration);

            await flow.ExecuteAsync(clientId, subscribe, channel.Object);

            senderFlow.Verify(f => f.SendPublishAsync(It.Is <string>(s => s == clientId),
                                                      It.Is <Publish>(p => p.Topic == retainedTopic &&
                                                                      p.QualityOfService == fooQoS &&
                                                                      p.Payload.ToList().SequenceEqual(retainedPayload) &&
                                                                      p.PacketId.HasValue &&
                                                                      p.Retain),
                                                      It.Is <IMqttChannel <IPacket> >(c => c == channel.Object),
                                                      It.Is <PendingMessageStatus>(x => x == PendingMessageStatus.PendingToSend)));
        }
        public async Task when_subscribing_new_topics_then_subscriptions_are_created_and_ack_is_sent()
        {
            MqttConfiguration configuration = new MqttConfiguration {
                MaximumQualityOfService = MqttQualityOfService.AtLeastOnce
            };
            Mock <IMqttTopicEvaluator>          topicEvaluator      = new Mock <IMqttTopicEvaluator>();
            Mock <IRepository <ClientSession> > sessionRepository   = new Mock <IRepository <ClientSession> >();
            IPacketIdProvider             packetIdProvider          = Mock.Of <IPacketIdProvider>();
            IRepository <RetainedMessage> retainedMessageRepository = Mock.Of <IRepository <RetainedMessage> >();
            IPublishSenderFlow            senderFlow = Mock.Of <IPublishSenderFlow>();

            string        clientId = Guid.NewGuid().ToString();
            ClientSession session  = new ClientSession(clientId, clean: false);

            topicEvaluator.Setup(e => e.IsValidTopicFilter(It.IsAny <string>())).Returns(true);
            sessionRepository.Setup(r => r.Read(It.IsAny <string>())).Returns(session);

            MqttQualityOfService fooQoS          = MqttQualityOfService.AtLeastOnce;
            string               fooTopic        = "test/foo/1";
            Subscription         fooSubscription = new Subscription(fooTopic, fooQoS);
            MqttQualityOfService barQoS          = MqttQualityOfService.AtMostOnce;
            string               barTopic        = "test/bar/1";
            Subscription         barSubscription = new Subscription(barTopic, barQoS);

            ushort    packetId  = (ushort)new Random().Next(0, ushort.MaxValue);
            Subscribe subscribe = new Subscribe(packetId, fooSubscription, barSubscription);

            Mock <IMqttChannel <IPacket> > channel = new Mock <IMqttChannel <IPacket> >();

            IPacket response = default;

            channel.Setup(c => c.SendAsync(It.IsAny <IPacket>()))
            .Callback <IPacket>(p => response = p)
            .Returns(Task.Delay(0));

            Mock <IConnectionProvider> connectionProvider = new Mock <IConnectionProvider>();

            connectionProvider
            .Setup(p => p.GetConnection(It.Is <string>(c => c == clientId)))
            .Returns(channel.Object);

            ServerSubscribeFlow flow = new ServerSubscribeFlow(topicEvaluator.Object, sessionRepository.Object,
                                                               retainedMessageRepository, packetIdProvider, senderFlow, configuration);

            await flow.ExecuteAsync(clientId, subscribe, channel.Object);

            sessionRepository.Verify(r => r.Update(It.Is <ClientSession>(s => s.Id == clientId && s.Subscriptions.Count == 2 &&
                                                                         s.Subscriptions.All(x => x.TopicFilter == fooTopic || x.TopicFilter == barTopic))));
            Assert.NotNull(response);

            SubscribeAck subscribeAck = response as SubscribeAck;

            Assert.NotNull(subscribeAck);
            packetId.Should().Be(subscribeAck.PacketId);
            2.Should().Be(subscribeAck.ReturnCodes.Count());
            Assert.True(subscribeAck.ReturnCodes.Any(c => c == SubscribeReturnCode.MaximumQoS0));
            Assert.True(subscribeAck.ReturnCodes.Any(c => c == SubscribeReturnCode.MaximumQoS1));
        }
Пример #16
0
        /// <summary>
        /// Sets properties and attributes of class in accordance with XML definition.
        /// </summary>
        /// <param name="Definition">XML definition</param>
        public override Task FromXml(XmlElement Definition)
        {
            this.actor  = new StringAttribute(XML.Attribute(Definition, "actor"));
            this.topic  = new StringAttribute(XML.Attribute(Definition, "topic"));
            this.qos    = (MqttQualityOfService)XML.Attribute(Definition, "qos", MqttQualityOfService.AtMostOnce);
            this.retain = XML.Attribute(Definition, "retain", false);

            return(base.FromXml(Definition));
        }
Пример #17
0
 public MessageReceivedBookmark(string topic, string host, int port, string username, string password, MqttQualityOfService qos)
 {
     Topic    = topic;
     Host     = host;
     Port     = port;
     Username = username;
     Password = password;
     Qos      = qos;
 }
Пример #18
0
 public MqttClientOptions(string topic, string host, int port, string username, string password, MqttQualityOfService qos)
 {
     Topic            = topic;
     Host             = host;
     Port             = port;
     Username         = username;
     Password         = password;
     QualityOfService = qos;
 }
Пример #19
0
        private async Task <ushort> PUBLISH(string Topic, MqttQualityOfService QoS, bool Retain, bool Duplicate, byte[] Data)
        {
            BinaryOutput Payload = new BinaryOutput();
            ushort       PacketIdentifier;

            Payload.WriteString(Topic);

            if (QoS > MqttQualityOfService.AtMostOnce)
            {
                PacketIdentifier = this.packetIdentifier++;
                if (PacketIdentifier == 0)
                {
                    PacketIdentifier = this.packetIdentifier++;
                }

                Payload.WriteUInt16(PacketIdentifier);
            }
            else
            {
                PacketIdentifier = 0;
            }

            Payload.WriteBytes(Data);

            byte[] PayloadData = Payload.GetPacket();

            BinaryOutput Packet = new BinaryOutput();
            byte         b      = (byte)((int)MqttControlPacketType.PUBLISH << 4);

            if (Duplicate)
            {
                b |= 8;
            }

            b |= (byte)((int)QoS << 1);

            if (Retain)
            {
                b |= 1;
            }

            Packet.WriteByte(b);
            Packet.WriteUInt((uint)PayloadData.Length);
            Packet.WriteBytes(PayloadData);

            byte[] PacketData = Packet.GetPacket();

            if (this.HasSniffers)
            {
                this.Information("PUBLISH(" + QoS.ToString() + ":" + Topic + ")");
            }

            await this.Write(PacketData, PacketIdentifier, null);

            return(PacketIdentifier);
        }
Пример #20
0
        public ConsumerWorkflow(IConfiguration configuration)
        {
            var section = configuration.GetSection("Mqtt");

            _host     = section.GetValue <string>("Host");
            _port     = section.GetValue <int>("Port");
            _username = section.GetValue <string>("Username");
            _password = section.GetValue <string>("Password");
            _qos      = section.GetValue <MqttQualityOfService>("QualityOfService");
        }
Пример #21
0
        private ushort PUBLISH(string Topic, MqttQualityOfService QoS, bool Retain, bool Duplicate, byte[] Data)
        {
            BinaryOutput Payload = new BinaryOutput();
            ushort       PacketIdentifier;

            Payload.WriteString(Topic);

            if (QoS > MqttQualityOfService.AtMostOnce)
            {
                PacketIdentifier = this.packetIdentifier++;
                if (PacketIdentifier == 0)
                {
                    PacketIdentifier = this.packetIdentifier++;
                }

                Payload.WriteUInt16(PacketIdentifier);
            }
            else
            {
                PacketIdentifier = 0;
            }

            Payload.WriteBytes(Data);

            byte[] PayloadData = Payload.GetPacket();

            BinaryOutput Packet = new BinaryOutput();
            byte         b      = (byte)((int)MqttControlPacketType.PUBLISH << 4);

            if (Duplicate)
            {
                b |= 8;
            }

            b |= (byte)((int)QoS << 1);

            if (Retain)
            {
                b |= 1;
            }

            Packet.WriteByte(b);
            Packet.WriteUInt((uint)PayloadData.Length);
            Packet.WriteBytes(PayloadData);

            byte[] PacketData = Packet.GetPacket();

            this.BeginWrite(PacketData, PacketIdentifier, null);

            return(PacketIdentifier);
        }
Пример #22
0
        public void SetWill(string WillTopic, string WillData, bool WillRetain, MqttQualityOfService WillQoS)
        {
            if (this.willTopic != WillTopic || this.willData != WillData || this.willRetain != WillRetain || this.willQoS != WillQoS)
            {
                this.Close();

                this.willTopic  = WillTopic;
                this.willData   = WillData;
                this.willRetain = WillRetain;
                this.willQoS    = WillQoS;

                this.Open();
            }
        }
Пример #23
0
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            JObject jObject = JObject.Load(reader);

            string topic             = jObject["topic"].ToObject <string>();
            MqttQualityOfService qos = jObject["qualityOfService"].ToObject <MqttQualityOfService>();
            bool   retain            = jObject["retain"].ToObject <bool>();
            string message           = jObject["message"].ToObject <string>();
            bool   hasMessage        = !string.IsNullOrEmpty((message));

            byte[] payload = hasMessage ? Encoding.UTF8.GetBytes(message) : jObject["message"].ToObject <byte[]>();

            return(new MqttLastWill(topic, qos, retain, payload));
        }
Пример #24
0
        async Task DispatchAsync(Publish publish, ClientSubscription subscription, bool isWill = false)
        {
            MqttQualityOfService requestedQos = isWill ? publish.QualityOfService : subscription.MaximumQualityOfService;
            MqttQualityOfService supportedQos = configuration.GetSupportedQos(requestedQos);
            bool    retain              = isWill ? publish.Retain : false;
            ushort? packetId            = supportedQos == MqttQualityOfService.AtMostOnce ? null : (ushort?)_packetIdProvider.GetPacketId();
            Publish subscriptionPublish = new Publish(publish.Topic, supportedQos, retain, duplicated: false, packetId: packetId)
            {
                Payload = publish.Payload
            };
            IMqttChannel <IPacket> clientChannel = _connectionProvider.GetConnection(subscription.ClientId);

            await _senderFlow.SendPublishAsync(subscription.ClientId, subscriptionPublish, clientChannel);
        }
Пример #25
0
        protected override Publish Read(byte[] bytes)
        {
            int remainingLength = MqttProtocol.Encoding.DecodeRemainingLength(bytes, out int remainingLengthBytesLength);

            byte packetFlags = bytes.Byte(0).Bits(5, 4);

            if (packetFlags.Bits(6, 2) == 0x03)
            {
                throw new MqttException(ClientProperties.Formatter_InvalidQualityOfService);
            }

            MqttQualityOfService qos = (MqttQualityOfService)packetFlags.Bits(6, 2);
            bool duplicated          = packetFlags.IsSet(3);

            if (qos == MqttQualityOfService.AtMostOnce && duplicated)
            {
                throw new MqttException(ClientProperties.PublishFormatter_InvalidDuplicatedWithQoSZero);
            }

            bool retainFlag = packetFlags.IsSet(0);

            int    topicStartIndex = 1 + remainingLengthBytesLength;
            string topic           = bytes.GetString(topicStartIndex, out int nextIndex);

            if (!_topicEvaluator.IsValidTopicName(topic))
            {
                throw new MqttException(ClientProperties.PublishFormatter_InvalidTopicName(topic));
            }

            int    variableHeaderLength = topic.Length + 2;
            ushort?packetId             = default;

            if (qos != MqttQualityOfService.AtMostOnce)
            {
                packetId              = bytes.Bytes(nextIndex, 2).ToUInt16();
                variableHeaderLength += 2;
            }

            Publish publish = new Publish(topic, qos, retainFlag, duplicated, packetId);

            if (remainingLength > variableHeaderLength)
            {
                int payloadStartIndex = 1 + remainingLengthBytesLength + variableHeaderLength;

                publish.Payload = bytes.Bytes(payloadStartIndex);
            }

            return(publish);
        }
Пример #26
0
 async Task SendQosAck(string clientId, MqttQualityOfService qos, Publish publish, IMqttChannel <IPacket> channel)
 {
     if (qos == MqttQualityOfService.AtMostOnce)
     {
         return;
     }
     else if (qos == MqttQualityOfService.AtLeastOnce)
     {
         await SendAckAsync(clientId, new PublishAck( publish.PacketId.Value ), channel);
     }
     else
     {
         await SendAckAsync(clientId, new PublishReceived( publish.PacketId.Value ), channel);
     }
 }
        public async Task when_client_disconnects_by_protocol_then_will_message_is_not_sent()
        {
            using (IMqttClient client1 = await GetClientAsync())
                using (IMqttClient client2 = await GetClientAsync())
                    using (IMqttClient client3 = await GetClientAsync())
                    {
                        string topic               = Guid.NewGuid().ToString();
                        MqttQualityOfService qos   = MqttQualityOfService.ExactlyOnce;
                        bool           retain      = true;
                        FooWillMessage willMessage = new FooWillMessage {
                            Message = "Client 1 has been disconnected unexpectedly"
                        };
                        MqttLastWill will = new MqttLastWill(topic, qos, retain, willMessage.GetPayload());

                        await client1.ConnectAsync(new MqttClientCredentials( MqttTestHelper.GetClientId()), will);

                        await client2.ConnectAsync(new MqttClientCredentials( MqttTestHelper.GetClientId()));

                        await client3.ConnectAsync(new MqttClientCredentials( MqttTestHelper.GetClientId()));

                        await client2.SubscribeAsync(topic, MqttQualityOfService.AtMostOnce);

                        await client3.SubscribeAsync(topic, MqttQualityOfService.AtLeastOnce);

                        ManualResetEventSlim willReceivedSignal = new ManualResetEventSlim(initialState: false);

                        client2.MessageStream.Subscribe(m =>
                        {
                            if (m.Topic == topic)
                            {
                                willReceivedSignal.Set();
                            }
                        });
                        client3.MessageStream.Subscribe(m =>
                        {
                            if (m.Topic == topic)
                            {
                                willReceivedSignal.Set();
                            }
                        });

                        await client1.DisconnectAsync();

                        bool willReceived = willReceivedSignal.Wait(2000);

                        Assert.False(willReceived);
                    }
        }
Пример #28
0
        public async Task when_unsubscribing_existing_subscriptions_then_subscriptions_are_deleted_and_ack_is_sent()
        {
            Mock <IRepository <ClientSession> > sessionRepository = new Mock <IRepository <ClientSession> >();
            string clientId              = Guid.NewGuid().ToString();
            ushort packetId              = (ushort)new Random().Next(0, ushort.MaxValue);
            string topic                 = "foo/bar/test";
            MqttQualityOfService qos     = MqttQualityOfService.AtLeastOnce;
            ClientSession        session = new ClientSession(clientId, clean: false)
            {
                Subscriptions = new List <ClientSubscription> {
                    new ClientSubscription {
                        ClientId = clientId, MaximumQualityOfService = qos, TopicFilter = topic
                    }
                }
            };
            ClientSession updatedSession = default;

            sessionRepository.Setup(r => r.Read(It.IsAny <string>())).Returns(session);
            sessionRepository.Setup(r => r.Update(It.IsAny <ClientSession>())).Callback <ClientSession>(s => updatedSession = s);

            Unsubscribe unsubscribe = new Unsubscribe(packetId, topic);

            Mock <IMqttChannel <IPacket> > channel = new Mock <IMqttChannel <IPacket> >();

            IPacket response = default;

            channel.Setup(c => c.SendAsync(It.IsAny <IPacket>()))
            .Callback <IPacket>(p => response = p)
            .Returns(Task.Delay(0));

            Mock <IConnectionProvider> connectionProvider = new Mock <IConnectionProvider>();

            connectionProvider
            .Setup(p => p.GetConnection(It.Is <string>(c => c == clientId)))
            .Returns(channel.Object);

            ServerUnsubscribeFlow flow = new ServerUnsubscribeFlow(sessionRepository.Object);

            await flow.ExecuteAsync(clientId, unsubscribe, channel.Object);

            Assert.NotNull(response);
            0.Should().Be(updatedSession.Subscriptions.Count);

            UnsubscribeAck unsubscribeAck = response as UnsubscribeAck;

            Assert.NotNull(unsubscribeAck);
            packetId.Should().Be(unsubscribeAck.PacketId);
        }
Пример #29
0
        public async void PublishAsync(
            string topic,
            byte[] payload,
            MqttQualityOfService qos = MqttQualityOfService.AtMostOnce)
        {
            var sessionState = await Client.ConnectAsync(Credentials);

            var message = new MqttApplicationMessage(topic, payload);

            await Client.PublishAsync(message, qos);

            await Client.DisconnectAsync();

            // 若不中斷連接,此線不會結束。
            return;
        }
Пример #30
0
        public MqttBroker(MqttBrokerNode Node, string Host, int Port, bool Tls, string UserName, string Password,
                          string WillTopic, string WillData, bool WillRetain, MqttQualityOfService WillQoS)
        {
            this.node       = Node;
            this.host       = Host;
            this.port       = Port;
            this.tls        = Tls;
            this.userName   = UserName;
            this.password   = Password;
            this.willTopic  = WillTopic;
            this.willData   = WillData;
            this.willRetain = WillRetain;
            this.willQoS    = WillQoS;

            this.Open();
        }
Пример #31
0
		/// <summary>
		/// Publishes information on a topic.
		/// </summary>
		/// <param name="Topic">Topic name</param>
		/// <param name="QoS">Quality of service</param>
		/// <param name="Retain">If topic shoudl retain information.</param>
		/// <param name="Data">Binary data to send.</param>
		/// <returns>Packet identifier assigned to data.</returns>
		public int PUBLISH(string Topic, MqttQualityOfService QoS, bool Retain, byte[] Data)
		{
			return this.PUBLISH(Topic, QoS, Retain, false, Data);
		}
Пример #32
0
		/// <summary>
		/// Publishes information on a topic.
		/// </summary>
		/// <param name="Topic">Topic name</param>
		/// <param name="QoS">Quality of service</param>
		/// <param name="Retain">If topic shoudl retain information.</param>
		/// <param name="Data">Binary data to send.</param>
		/// <returns>Packet identifier assigned to data.</returns>
		public int PUBLISH(string Topic, MqttQualityOfService QoS, bool Retain, BinaryOutput Data)
		{
			return this.PUBLISH(Topic, QoS, Retain, false, Data.GetPacket());
		}
Пример #33
0
		private ushort PUBLISH(string Topic, MqttQualityOfService QoS, bool Retain, bool Duplicate, byte[] Data)
		{
			BinaryOutput Payload = new BinaryOutput();
			ushort PacketIdentifier;

			Payload.WriteString(Topic);

			if (QoS > MqttQualityOfService.AtMostOne)
			{
				PacketIdentifier = this.packetIdentifier++;
				if (PacketIdentifier == 0)
					PacketIdentifier = this.packetIdentifier++;

				Payload.WriteUInt16(PacketIdentifier);
			}
			else
				PacketIdentifier = 0;

			Payload.WriteBytes(Data);

			byte[] PayloadData = Payload.GetPacket();

			BinaryOutput Packet = new BinaryOutput();
			byte b = (byte)((int)MqttControlPacketType.PUBLISH << 4);
			if (Duplicate)
				b |= 8;

			b |= (byte)((int)QoS << 1);

			if (Retain)
				b |= 1;

			Packet.WriteByte(b);
			Packet.WriteUInt((uint)PayloadData.Length);
			Packet.WriteBytes(PayloadData);

			byte[] PacketData = Packet.GetPacket();

			this.BeginWrite(PacketData, PacketIdentifier);

			return PacketIdentifier;
		}