public void when_sending_connect_with_invalid_user_credentials_then_connection_exception_is_thrown()
        {
            IMqttAuthenticationProvider          authenticationProvider = Mock.Of <IMqttAuthenticationProvider>(p => p.Authenticate(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>()) == false);
            Mock <IRepository <ClientSession> >  sessionRepository      = new Mock <IRepository <ClientSession> >();
            Mock <IRepository <ConnectionWill> > willRepository         = new Mock <IRepository <ConnectionWill> >();
            Mock <IPublishSenderFlow>            senderFlow             = new Mock <IPublishSenderFlow>();

            string  clientId = Guid.NewGuid().ToString();
            Connect connect  = new Connect(clientId, cleanSession: true, MqttProtocol.SupportedLevel);
            Mock <IMqttChannel <IPacket> > channel = new Mock <IMqttChannel <IPacket> >();
            IPacket sentPacket = default;

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

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

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

            ServerConnectFlow flow = new ServerConnectFlow(authenticationProvider, sessionRepository.Object, willRepository.Object, senderFlow.Object);

            AggregateException aggregateEx = Assert.Throws <AggregateException>(() => flow.ExecuteAsync(clientId, connect, channel.Object).Wait());

            Assert.NotNull(aggregateEx.InnerException);
            Assert.True(aggregateEx.InnerException is MqttConnectionException);
            ((MqttConnectionException)aggregateEx.InnerException).ReturnCode.Should()
            .Be(MqttConnectionStatus.BadUserNameOrPassword);
        }
Пример #2
0
 public ServerConnectFlow(IMqttAuthenticationProvider authenticationProvider,
                          IRepository <ClientSession> sessionRepository,
                          IRepository <ConnectionWill> willRepository,
                          IPublishSenderFlow senderFlow)
 {
     this.authenticationProvider = authenticationProvider;
     this.sessionRepository      = sessionRepository;
     this.willRepository         = willRepository;
     this.senderFlow             = senderFlow;
 }
        public void when_getting_server_flow_from_valid_packet_type_then_succeeds(MqttPacketType packetType, Type flowType)
        {
            IMqttAuthenticationProvider authenticationProvider = Mock.Of <IMqttAuthenticationProvider>(p => p.Authenticate(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>()) == true);
            ServerProtocolFlowProvider  flowProvider           = new ServerProtocolFlowProvider(authenticationProvider, Mock.Of <IConnectionProvider>(), Mock.Of <IMqttTopicEvaluator>(),
                                                                                                Mock.Of <IRepositoryProvider>(), Mock.Of <IPacketIdProvider>(), Mock.Of <ISubject <MqttUndeliveredMessage> >(), new MqttConfiguration());

            IProtocolFlow flow = flowProvider.GetFlow(packetType);

            flowType.Should().Be(flow.GetType());
        }
 public ServerProtocolFlowProvider(IMqttAuthenticationProvider authenticationProvider,
                                   IConnectionProvider connectionProvider,
                                   IMqttTopicEvaluator topicEvaluator,
                                   IRepositoryProvider repositoryProvider,
                                   IPacketIdProvider packetIdProvider,
                                   ISubject <MqttUndeliveredMessage> undeliveredMessagesListener,
                                   MqttConfiguration configuration)
     : base(topicEvaluator, repositoryProvider, configuration)
 {
     _authenticationProvider      = authenticationProvider;
     _connectionProvider          = connectionProvider;
     _packetIdProvider            = packetIdProvider;
     _undeliveredMessagesListener = undeliveredMessagesListener;
 }
 protected IntegrationContext(ushort keepAliveSecs = 5, bool allowWildcardsInTopicFilters = true, IMqttAuthenticationProvider authenticationProvider = null)
 {
     KeepAliveSecs = keepAliveSecs;
     AllowWildcardsInTopicFilters = allowWildcardsInTopicFilters;
     _authenticationProvider      = authenticationProvider;
     Configuration = new MqttConfiguration
     {
         BufferSize                   = 128 * 1024,
         Port                         = 25565,
         KeepAliveSecs                = KeepAliveSecs,
         WaitTimeoutSecs              = 5,
         MaximumQualityOfService      = MqttQualityOfService.ExactlyOnce,
         AllowWildcardsInTopicFilters = AllowWildcardsInTopicFilters
     };
 }
        public async Task when_sending_connect_with_will_then_will_is_created_and_ack_is_sent()
        {
            IMqttAuthenticationProvider          authenticationProvider = Mock.Of <IMqttAuthenticationProvider>(p => p.Authenticate(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>()) == true);
            Mock <IRepository <ClientSession> >  sessionRepository      = new Mock <IRepository <ClientSession> >();
            Mock <IRepository <ConnectionWill> > willRepository         = new Mock <IRepository <ConnectionWill> >();

            Mock <IPublishSenderFlow> senderFlow = new Mock <IPublishSenderFlow>();

            string  clientId = Guid.NewGuid().ToString();
            Connect connect  = new Connect(clientId, cleanSession: true, MqttProtocol.SupportedLevel);

            FooWillMessage willMessage = new FooWillMessage {
                Message = "Foo Will Message"
            };
            MqttLastWill will = new MqttLastWill("foo/bar", MqttQualityOfService.AtLeastOnce, retain: true, payload: willMessage.GetPayload());

            connect.Will = will;

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

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

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

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

            ServerConnectFlow flow = new ServerConnectFlow(authenticationProvider, sessionRepository.Object, willRepository.Object, senderFlow.Object);

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

            ConnectAck connectAck = sentPacket as ConnectAck;

            sessionRepository.Verify(r => r.Delete(It.IsAny <string>()), Times.Never);
            sessionRepository.Verify(r => r.Create(It.Is <ClientSession>(s => s.Id == clientId && s.Clean == true)));
            willRepository.Verify(r => r.Create(It.Is <ConnectionWill>(w => w.Id == clientId && w.Will == will)));

            Assert.NotNull(connectAck);
            connectAck.Type.Should().Be(MqttPacketType.ConnectAck);
            connectAck.Status.Should().Be(MqttConnectionStatus.Accepted);
            Assert.False(connectAck.SessionPresent);
        }
        public async Task when_sending_connect_with_existing_session_and_without_clean_session_then_session_is_not_deleted_and_ack_is_sent_with_session_present()
        {
            IMqttAuthenticationProvider          authenticationProvider = Mock.Of <IMqttAuthenticationProvider>(p => p.Authenticate(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>()) == true);
            Mock <IRepository <ClientSession> >  sessionRepository      = new Mock <IRepository <ClientSession> >();
            Mock <IRepository <ConnectionWill> > willRepository         = new Mock <IRepository <ConnectionWill> >();

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

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

            Mock <IPublishSenderFlow> senderFlow = new Mock <IPublishSenderFlow>();

            Connect connect = new Connect(clientId, cleanSession: false, MqttProtocol.SupportedLevel);
            Mock <IMqttChannel <IPacket> > channel = new Mock <IMqttChannel <IPacket> >();
            IPacket sentPacket = default;

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

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

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

            ServerConnectFlow flow = new ServerConnectFlow(authenticationProvider, sessionRepository.Object, willRepository.Object, senderFlow.Object);

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

            sessionRepository.Verify(r => r.Create(It.IsAny <ClientSession>()), Times.Never);
            sessionRepository.Verify(r => r.Delete(It.IsAny <string>()), Times.Never);
            willRepository.Verify(r => r.Create(It.IsAny <ConnectionWill>()), Times.Never);

            ConnectAck connectAck = sentPacket as ConnectAck;

            Assert.NotNull(connectAck);
            connectAck.Type.Should().Be(MqttPacketType.ConnectAck);
            connectAck.Status.Should().Be(MqttConnectionStatus.Accepted);

            connectAck.SessionPresent.Should().BeTrue();
        }
        public void when_getting_explicit_server_flow_from_type_then_succeeds()
        {
            IMqttAuthenticationProvider authenticationProvider = Mock.Of <IMqttAuthenticationProvider>(p => p.Authenticate(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>()) == true);
            ServerProtocolFlowProvider  flowProvider           = new ServerProtocolFlowProvider(authenticationProvider, Mock.Of <IConnectionProvider>(), Mock.Of <IMqttTopicEvaluator>(),
                                                                                                Mock.Of <IRepositoryProvider>(), Mock.Of <IPacketIdProvider>(), Mock.Of <ISubject <MqttUndeliveredMessage> >(), new MqttConfiguration());

            ServerConnectFlow         connectFlow     = flowProvider.GetFlow <ServerConnectFlow>();
            PublishSenderFlow         senderFlow      = flowProvider.GetFlow <PublishSenderFlow>();
            ServerPublishReceiverFlow receiverFlow    = flowProvider.GetFlow <ServerPublishReceiverFlow>();
            ServerSubscribeFlow       subscribeFlow   = flowProvider.GetFlow <ServerSubscribeFlow>();
            ServerUnsubscribeFlow     unsubscribeFlow = flowProvider.GetFlow <ServerUnsubscribeFlow>();
            DisconnectFlow            disconnectFlow  = flowProvider.GetFlow <DisconnectFlow>();

            Assert.NotNull(connectFlow);
            Assert.NotNull(senderFlow);
            Assert.NotNull(receiverFlow);
            Assert.NotNull(subscribeFlow);
            Assert.NotNull(unsubscribeFlow);
            Assert.NotNull(disconnectFlow);
        }
        protected async Task <IMqttServer> GetServerAsync(IMqttAuthenticationProvider authenticationProvider = null)
        {
            try {
                LoadConfiguration();

                var server = MqttServer.Create(Configuration, authenticationProvider: authenticationProvider);

                server.Start();

                return(server);
            } catch (MqttException protocolEx) {
                if (protocolEx.InnerException is SocketException)
                {
                    return(await GetServerAsync());
                }
                else
                {
                    throw;
                }
            }
        }
Пример #10
0
        protected async Task <IMqttServer> GetServerAsync(IMqttAuthenticationProvider authenticationProvider = null)
        {
            try {
                LoadConfiguration();

                var binding     = new ServerTcpBinding();
                var initializer = new MqttServerFactory(binding, authenticationProvider);
                var server      = initializer.CreateServer(Configuration);

                server.Start();

                return(server);
            } catch (MqttException protocolEx) {
                if (protocolEx.InnerException is SocketException)
                {
                    return(await GetServerAsync());
                }
                else
                {
                    throw;
                }
            }
        }
Пример #11
0
 /// <summary>
 /// Initializes a new instance of the <see cref="MqttServerFactory" /> class,
 /// spcifying the transport protocol binding to use and optionally the
 /// authentication provider to enable authentication as part of the connection mechanism.
 /// </summary>
 /// <param name="binding">
 /// Transport protocol binding to use as the MQTT underlying protocol
 /// See <see cref="IMqttServerBinding" /> for more details about how to implement it
 /// </param>
 /// <param name="authenticationProvider">
 /// Optional authentication provider to use,
 /// to enable authentication as part of the connection mechanism
 /// See <see cref="IMqttAuthenticationProvider" /> for more details about how to implement
 /// an authentication provider
 /// </param>
 public MqttServerFactory(IMqttServerBinding binding, IMqttAuthenticationProvider authenticationProvider = null)
 {
     this.binding = binding;
     this.authenticationProvider = authenticationProvider ?? NullAuthenticationProvider.Instance;
 }
Пример #12
0
 /// <summary>
 /// Initializes a new instance of the <see cref="MqttServerFactory" /> class,
 /// with the option to define an authentication provider to enable authentication
 /// as part of the connection mechanism.
 /// It also uses TCP as the default transport protocol binding
 /// </summary>
 /// <param name="authenticationProvider">
 /// Optional authentication provider to use,
 /// to enable authentication as part of the connection mechanism
 /// See <see cref="IMqttAuthenticationProvider" /> for more details about how to implement
 /// an authentication provider
 /// </param>
 public MqttServerFactory(IMqttAuthenticationProvider authenticationProvider = null)
     : this(new ServerTcpBinding(), authenticationProvider)
 {
 }
        public async Task when_sending_connect_with_existing_session_and_without_clean_session_then_pending_messages_and_acks_are_sent()
        {
            IMqttAuthenticationProvider          authenticationProvider = Mock.Of <IMqttAuthenticationProvider>(p => p.Authenticate(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>()) == true);
            Mock <IRepository <ClientSession> >  sessionRepository      = new Mock <IRepository <ClientSession> >();
            Mock <IRepository <ConnectionWill> > willRepository         = new Mock <IRepository <ConnectionWill> >();

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

            string topic = "foo/bar";

            byte[] payload           = new byte[10];
            MqttQualityOfService qos = MqttQualityOfService.ExactlyOnce;
            ushort packetId          = 10;

            existingSession.PendingMessages = new List <PendingMessage>
            {
                new PendingMessage {
                    Status           = PendingMessageStatus.PendingToSend,
                    Topic            = topic,
                    QualityOfService = qos,
                    Retain           = false,
                    Duplicated       = false,
                    PacketId         = packetId,
                    Payload          = payload
                },
                new PendingMessage {
                    Status           = PendingMessageStatus.PendingToAcknowledge,
                    Topic            = topic,
                    QualityOfService = qos,
                    Retain           = false,
                    Duplicated       = false,
                    PacketId         = packetId,
                    Payload          = payload
                }
            };

            existingSession.PendingAcknowledgements = new List <PendingAcknowledgement>
            {
                new PendingAcknowledgement {
                    Type = MqttPacketType.PublishReceived, PacketId = packetId
                }
            };

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

            Mock <IPublishSenderFlow> senderFlow = new Mock <IPublishSenderFlow>();

            senderFlow
            .Setup(f => f.SendPublishAsync(It.IsAny <string>(), It.IsAny <Publish>(), It.IsAny <IMqttChannel <IPacket> >(), It.IsAny <PendingMessageStatus>()))
            .Callback <string, Publish, IMqttChannel <IPacket>, PendingMessageStatus>(async(id, pub, ch, stat) =>
            {
                await ch.SendAsync(pub);
            })
            .Returns(Task.Delay(0));

            senderFlow
            .Setup(f => f.SendAckAsync(It.IsAny <string>(), It.IsAny <IFlowPacket>(), It.IsAny <IMqttChannel <IPacket> >(), It.IsAny <PendingMessageStatus>()))
            .Callback <string, IFlowPacket, IMqttChannel <IPacket>, PendingMessageStatus>(async(id, pack, ch, stat) =>
            {
                await ch.SendAsync(pack);
            })
            .Returns(Task.Delay(0));

            Connect connect = new Connect(clientId, cleanSession: false, MqttProtocol.SupportedLevel);
            Mock <IMqttChannel <IPacket> > channel = new Mock <IMqttChannel <IPacket> >();
            IPacket        firstPacket             = default;
            List <IPacket> nextPackets             = new List <IPacket>();

            channel
            .Setup(c => c.SendAsync(It.IsAny <IPacket>()))
            .Callback <IPacket>(packet =>
            {
                if (firstPacket == default(IPacket))
                {
                    firstPacket = packet;
                }
                else
                {
                    nextPackets.Add(packet);
                }
            })
            .Returns(Task.Delay(0));

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

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

            ServerConnectFlow flow = new ServerConnectFlow(authenticationProvider, sessionRepository.Object, willRepository.Object, senderFlow.Object);

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

            sessionRepository.Verify(r => r.Create(It.IsAny <ClientSession>()), Times.Never);
            sessionRepository.Verify(r => r.Delete(It.IsAny <string>()), Times.Never);
            sessionRepository.Verify(r => r.Update(It.IsAny <ClientSession>()), Times.Once);
            willRepository.Verify(r => r.Create(It.IsAny <ConnectionWill>()), Times.Never);
            senderFlow.Verify(f => f.SendPublishAsync(It.Is <string>(x => x == existingSession.Id),
                                                      It.Is <Publish>(x => x.Topic == topic && x.QualityOfService == qos && x.PacketId == packetId),
                                                      It.IsAny <IMqttChannel <IPacket> >(),
                                                      It.IsAny <PendingMessageStatus>()), Times.Exactly(2));
            senderFlow.Verify(f => f.SendAckAsync(It.Is <string>(x => x == existingSession.Id),
                                                  It.Is <IFlowPacket>(x => x.Type == MqttPacketType.PublishReceived && x.PacketId == packetId),
                                                  It.IsAny <IMqttChannel <IPacket> >(),
                                                  It.Is <PendingMessageStatus>(x => x == PendingMessageStatus.PendingToAcknowledge)), Times.Once);

            ConnectAck connectAck = firstPacket as ConnectAck;

            Assert.True(connectAck != null, "The first packet sent by the Server must be a CONNACK");
            connectAck.Type.Should().Be(MqttPacketType.ConnectAck);
            connectAck.Status.Should().Be(MqttConnectionStatus.Accepted);

            Assert.True(connectAck.SessionPresent);
            nextPackets.Count.Should().Be(3);

            Assert.False(nextPackets.Any(x => x is ConnectAck));
        }
Пример #14
0
 /// <summary>
 /// Creates an <see cref="IMqttServer"/> over the TCP protocol, using the
 /// specified MQTT configuration to customize the protocol parameters.
 /// </summary>
 /// <param name="configuration">
 /// The configuration used for creating the Server.
 /// See <see cref="MqttConfiguration" /> for more details about the supported values.
 /// </param>
 /// <param name="authenticationProvider">
 /// Optional authentication provider to use,
 /// to enable authentication as part of the connection mechanism.
 /// See <see cref="IMqttAuthenticationProvider" /> for more details about how to implement
 /// an authentication provider.
 /// </param>
 /// <returns>A new MQTT Server</returns>
 /// <exception cref="MqttServerException">MqttServerException</exception>
 public static IMqttServer Create(MqttConfiguration configuration, IMqttAuthenticationProvider authenticationProvider = null) =>
 new MqttServerFactory(authenticationProvider).CreateServer(configuration);
Пример #15
0
 /// <summary>
 /// Creates an <see cref="IMqttServer"/> using the specified MQTT configuration
 /// to customize the protocol parameters, and an optional transport binding and authentication provider.
 /// </summary>
 /// <param name="configuration">
 /// The configuration used for creating the Server.
 /// See <see cref="MqttConfiguration" /> for more details about the supported values.
 /// </param>
 /// <param name="binding">
 /// The binding to use as the underlying transport layer.
 /// Deafault value: <see cref="ServerTcpBinding"/>
 /// See <see cref="IMqttServerBinding"/> for more details about how
 /// to implement a custom binding
 /// </param>
 /// <param name="authenticationProvider">
 /// Optional authentication provider to use,
 /// to enable authentication as part of the connection mechanism.
 /// See <see cref="IMqttAuthenticationProvider" /> for more details about how to implement
 /// an authentication provider.
 /// </param>
 /// <returns>A new MQTT Server</returns>
 /// <exception cref="MqttServerException">MqttServerException</exception>
 public static IMqttServer Create(MqttConfiguration configuration, IMqttServerBinding binding = null, IMqttAuthenticationProvider authenticationProvider = null)
 => new MqttServerFactory(binding ?? new ServerTcpBinding(), authenticationProvider).CreateServer(configuration);