Beispiel #1
0
        /// <summary>
        /// Save session for a client (all related subscriptions)
        /// </summary>
        /// <param name="clientId">Client Id to save subscriptions</param>
        /// <param name="clientSession">Client session with inflight messages</param>
        /// <param name="subscriptions">Subscriptions to save</param>
        public void SaveSession(
            string clientId,
            MqttClientSession clientSession,
            List <MqttSubscription> subscriptions)
        {
            var session = Sessions.GetOrAdd(clientId, new MqttBrokerSession {
                ClientId = clientId
            });

            // null reference to disconnected client
            session.Connection = null;

            // update subscriptions
            session.Subscriptions = new List <MqttSubscription>();
            foreach (var subscription in subscriptions)
            {
                session.Subscriptions.Add(
                    new MqttSubscription(subscription.ClientId, subscription.Topic, subscription.QosLevel, null));
            }

            // update inflight messages
            session.InflightMessages = new ConcurrentDictionary <string, MqttMsgContext>();
            foreach (var msgContext in clientSession.InflightMessages.Values)
            {
                session.InflightMessages.TryAdd(msgContext.Key, msgContext);
            }
        }
Beispiel #2
0
        public async Task <MqttMessage> ProcessAsync(MqttClientSession clientSession, Packet packet)
        {
            if (!(packet is TPacket target))
            {
                return(MqttMessage.BAD_DATA_FORMAT);
            }

            return(await this.ProcessAsync(clientSession, target));
        }
        public Task <MqttMessage> ProcessAsync(MqttClientSession clientSession, Packet packet)
        {
            MqttMessage message = new MqttMessage {
                Code = -1
            };

            //TODO: 处理一些断开连接需要完成的任务

            return(Task.FromResult(message));
        }
        protected override Task <MqttMessage> ProcessAsync(MqttClientSession clientSession, DisconnectPacket packet)
        {
            MqttMessage message = new MqttMessage {
                Code = -1
            };

            //TODO: 处理一些断开连接需要完成的任务

            return(Task.FromResult(message));
        }
Beispiel #5
0
        protected override async Task <MqttMessage> ProcessAsync(MqttClientSession clientSession, PublishPacket packet)
        {
            List <string> clientIds = await subscriptionManager.GetSubscribeClientIds(packet.TopicName);

            if (clientIds != null && clientIds.Count > 0)
            {
                //循环依次发送信息
            }

            return(MqttMessage.SUCCESS);
        }
        /// <summary>
        /// Load a given session
        /// </summary>
        /// <param name="session">MQTT Client session to load</param>
        public void LoadSession(MqttClientSession session)
        {
            // if not clean session
            if (!this.CleanSession)
            {
                // set the session ...
                this.Session = session;

                // ... and restore it
                this.RestoreSession();
            }
        }
        public async Task <MqttMessage> ProcessAsync(MqttClientSession clientSession, Packet packet)
        {
            if (!(packet is UnsubscribePacket reqPacket))
            {
                this.logger.LogWarning("bad data format");
                return(null);
            }

            IMqttResult result = await this.subscriptionManager.UnSubscribe(clientSession, reqPacket);

            return(new MqttMessage {
                Code = result.Code
            });
        }
Beispiel #8
0
        protected override async Task <MqttMessage> ProcessAsync(MqttClientSession clientSession, ConnectPacket packet)
        {
            var ack       = new ConnAckPacket();
            var resultMsg = new MqttMessage {
                Packet = ack
            };

            _logger.LogInformation("receive connect packet ,clientId={0}", packet.ClientId);
            IMqttResult validResult = await _mqttAuthorize.Validate(packet);

            ack.ReturnCode = validResult.Code == 0 ? ConnectReturnCode.Accepted : ConnectReturnCode.RefusedNotAuthorized;

            return(resultMsg);
        }
Beispiel #9
0
        public async Task MqttSubscriptionsManager_SubscribeSingleNoSuccess()
        {
            var s = new MqttClientSession("", new ConcurrentDictionary <object, object>(),
                                          new MqttServerEventDispatcher(new TestLogger()), new MqttServerOptions(), new TestLogger());

            var sm = new MqttClientSubscriptionsManager(s, new MqttServerEventDispatcher(new TestLogger()), new MqttServerOptions());

            var sp = new MqttSubscribePacket();

            sp.TopicFilters.Add(new TopicFilterBuilder().WithTopic("A/B/C").Build());

            await sm.SubscribeAsync(sp, new MqttConnectPacket());

            Assert.IsFalse(sm.CheckSubscriptions("A/B/X", MqttQualityOfServiceLevel.AtMostOnce).IsSubscribed);
        }
Beispiel #10
0
        /// <summary>
        /// Save session for a client (all related subscriptions)
        /// </summary>
        /// <param name="clientId">Client Id to save subscriptions</param>
        /// <param name="clientSession">Client session with inflight messages</param>
        /// <param name="subscriptions">Subscriptions to save</param>
        public void SaveSession(string clientId, MqttClientSession clientSession, List <MqttSubscription> subscriptions)
        {
            MqttBrokerSession session = null;

            lock (this.sessions)
            {
                // session doesn't exist
                if (!this.sessions.ContainsKey(clientId))
                {
                    // create new session
                    session          = new MqttBrokerSession();
                    session.ClientId = clientId;

                    // add to sessions list
                    this.sessions.Add(clientId, session);
                }
                else
                {
                    // get existing session
                    session = this.sessions[clientId];
                }
            }

            // null reference to disconnected client
            session.Client = null;

            // update subscriptions
            session.Subscriptions = new List <MqttSubscription>();
            lock (session.Subscriptions)
            {
                foreach (MqttSubscription subscription in subscriptions)
                {
                    session.Subscriptions.Add(new MqttSubscription(subscription.ClientId, subscription.Topic, subscription.QosLevel, null));
                }
            }

            // update inflight messages
            session.InflightMessages = new Hashtable();
            lock (session.InflightMessages)
            {
                foreach (MqttMsgContext msgContext in clientSession.InflightMessages.Values)
                {
                    session.InflightMessages.Add(msgContext.Key, msgContext);
                }
            }
        }
Beispiel #11
0
        public async Task MqttSubscriptionsManager_SubscribeDifferentQoSSuccess()
        {
            var s = new MqttClientSession("", new ConcurrentDictionary <object, object>(),
                                          new MqttServerEventDispatcher(new TestLogger()), new MqttServerOptions(), new TestLogger());

            var sm = new MqttClientSubscriptionsManager(s, new MqttServerEventDispatcher(new TestLogger()), new MqttServerOptions());

            var sp = new MqttSubscribePacket();

            sp.TopicFilters.Add(new TopicFilter {
                Topic = "A/B/C", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce
            });

            await sm.SubscribeAsync(sp, new MqttConnectPacket());

            var result = sm.CheckSubscriptions("A/B/C", MqttQualityOfServiceLevel.ExactlyOnce);

            Assert.IsTrue(result.IsSubscribed);
            Assert.AreEqual(result.QualityOfServiceLevel, MqttQualityOfServiceLevel.AtMostOnce);
        }
Beispiel #12
0
        public async Task <MqttMessage> ProcessAsync(MqttClientSession clientSession, Packet packet)
        {
            var ack       = new ConnAckPacket();
            var resultMsg = new MqttMessage {
                Packet = ack
            };

            if (!(packet is ConnectPacket cntPacket))
            {
                this.logger.LogWarning("bad data format");
                ack.ReturnCode = ConnectReturnCode.RefusedNotAuthorized;
                return(resultMsg);
            }
            this.logger.LogWarning("receive connect packet ,clientId={0}", cntPacket.ClientId);
            IMqttResult validResult = await this.mqttAuthorize.Validate(cntPacket);

            ack.ReturnCode = validResult.Code == 0 ? ConnectReturnCode.Accepted : ConnectReturnCode.RefusedNotAuthorized;

            return(resultMsg);
        }
Beispiel #13
0
        void Client_MqttMsgConnected(object sender, MqttMsgConnectEventArgs e)
        {
            // [v3.1.1] session present flag
            bool sessionPresent = false;
            // [v3.1.1] generated client id for client who provides client id zero bytes length
            string clientId = null;

            MqttClient client = (MqttClient)sender;

            // verify message to determine CONNACK message return code to the client
            byte returnCode = this.MqttConnectVerify(e.Message);

            // [v3.1.1] if client id is zero length, the broker assigns a unique identifier to it
            clientId = (e.Message.ClientId.Length != 0) ? e.Message.ClientId : Guid.NewGuid().ToString();

            // connection "could" be accepted
            if (returnCode == MqttMsgConnack.CONN_ACCEPTED)
            {
                // check if there is a client already connected with same client Id
                MqttClient clientConnected = this.GetClient(clientId);

                // force connection close to the existing client (MQTT protocol)
                if (clientConnected != null)
                {
                    this.CloseClient(clientConnected);
                }
            }

            try
            {
                // connection accepted, load (if exists) client session
                if (returnCode == MqttMsgConnack.CONN_ACCEPTED)
                {
                    // check if not clean session and try to recovery a session
                    if (!e.Message.CleanSession)
                    {
                        // create session for the client
                        MqttClientSession clientSession = new MqttClientSession(clientId);

                        // get session for the connected client
                        MqttBrokerSession session = this.sessionManager.GetSession(clientId);

                        // set inflight queue into the client session
                        if (session != null)
                        {
                            clientSession.InflightMessages = session.InflightMessages;
                            // [v3.1.1] session present flag
                            if (client.ProtocolVersion == MqttProtocolVersion.Version_3_1_1)
                            {
                                sessionPresent = true;
                            }
                        }

                        // send CONNACK message to the client
                        client.Connack(e.Message, returnCode, clientId, sessionPresent);

                        // load/inject session to the client
                        client.LoadSession(clientSession);

                        if (session != null)
                        {
                            // set reference to connected client into the session
                            session.Client = client;

                            // there are saved subscriptions
                            if (session.Subscriptions != null)
                            {
                                // register all subscriptions for the connected client
                                foreach (MqttSubscription subscription in session.Subscriptions)
                                {
                                    this.subscriberManager.Subscribe(subscription.Topic, subscription.QosLevel, client);

                                    // publish retained message on the current subscription
                                    this.publisherManager.PublishRetaind(subscription.Topic, clientId);
                                }
                            }

                            // there are saved outgoing messages
                            if (session.OutgoingMessages.Count > 0)
                            {
                                // publish outgoing messages for the session
                                this.publisherManager.PublishSession(session.ClientId);
                            }
                        }

                        //signal
                        EventHandler <MqttClientEventArgs> handler = DidAcceptNewClient;
                        if (handler != null)
                        {
                            MqttClientEventArgs arg = new MqttClientEventArgs();
                            arg.Client = client;
                            handler(this, arg);
                        }
                    }
                    // requested clean session
                    else
                    {
                        // send CONNACK message to the client
                        client.Connack(e.Message, returnCode, clientId, sessionPresent);

                        this.sessionManager.ClearSession(clientId);
                    }
                }
                else
                {
                    // send CONNACK message to the client
                    client.Connack(e.Message, returnCode, clientId, sessionPresent);
                }
            }
            catch (MqttCommunicationException)
            {
                this.CloseClient(client);
            }
        }
Beispiel #14
0
 public MqttSessionStatus(MqttClientSession session, MqttClientSessionsManager sessionsManager)
 {
     _session         = session ?? throw new ArgumentNullException(nameof(session));
     _sessionsManager = sessionsManager ?? throw new ArgumentNullException(nameof(sessionsManager));
 }
Beispiel #15
0
 public void CleanSession()
 {
     session.Clear();
     session = new MqttClientSession(clientId);
 }
Beispiel #16
0
 public MqttSessionManager(string clientId)
 {
     this.clientId = clientId;
     session       = new MqttClientSession(clientId);
 }
Beispiel #17
0
 public Task <MqttMessage> ProcessAsync(MqttClientSession clientSession, Packet packet)
 {
     return(Task.FromResult(PingAckMsg));
 }
Beispiel #18
0
 public Task <MqttMessage> ProcessAsync(MqttClientSession clientSession, Packet packet)
 {
     return(null);
 }
        public void OnMqttMsgConnected(MqttClientConnection clientConnection, MqttMsgConnect message)
        {
            clientConnection.ProtocolVersion = (MqttProtocolVersion)message.ProtocolVersion;

            // verify message to determine CONNACK message return code to the client
            byte returnCode = MqttConnectVerify(message);

            // [v3.1.1] if client id is zero length, the broker assigns a unique identifier to it
            var clientId = (message.ClientId.Length != 0) ? message.ClientId : Guid.NewGuid().ToString();

            // connection "could" be accepted
            if (returnCode == MqttMsgConnack.CONN_ACCEPTED)
            {
                // check if there is a client already connected with same client Id
                MqttClientConnection clientConnectionConnected = MqttBroker.GetClientConnection(clientId);

                // force connection close to the existing client (MQTT protocol)
                if (clientConnectionConnected != null)
                {
                    OnConnectionClosed(clientConnectionConnected);
                }

                // add client to the collection
                MqttBroker.TryAddClientConnection(clientId, clientConnection);
                Interlocked.Increment(ref numberOfConnectedClients);
            }

            // connection accepted, load (if exists) client session
            if (returnCode == MqttMsgConnack.CONN_ACCEPTED)
            {
                // check if not clean session and try to recovery a session
                if (!message.CleanSession)
                {
                    // create session for the client
                    MqttClientSession clientSession = new MqttClientSession(clientId);

                    // get session for the connected client
                    MqttBrokerSession session = MqttSessionManager.GetSession(clientId);

                    // [v3.1.1] session present flag
                    bool sessionPresent = false;

                    // set inflight queue into the client session
                    if (session != null)
                    {
                        clientSession.InflightMessages = session.InflightMessages;
                        // [v3.1.1] session present flag
                        if (clientConnection.ProtocolVersion == MqttProtocolVersion.Version_3_1_1)
                        {
                            sessionPresent = true;
                        }
                    }

                    // send CONNACK message to the client
                    MqttOutgoingMessageManager.Connack(clientConnection, message, returnCode, clientId, sessionPresent);

                    // load/inject session to the client
                    clientConnection.LoadSession(clientSession);

                    if (session != null)
                    {
                        // set reference to connected client into the session
                        session.ClientConnection = clientConnection;

                        // there are saved subscriptions
                        if (session.Subscriptions != null)
                        {
                            // register all subscriptions for the connected client
                            foreach (MqttSubscription subscription in session.Subscriptions)
                            {
                                MqttSubscriberManager.Subscribe(
                                    subscription.Topic,
                                    subscription.QosLevel,
                                    clientConnection);

                                // publish retained message on the current subscription
                                RetainedMessageManager.PublishRetaind(subscription.Topic, clientConnection);
                            }
                        }

                        // there are saved outgoing messages
                        if (session.OutgoingMessages.Count > 0)
                        {
                            // publish outgoing messages for the session
                            this.publishManager.PublishSession(session.ClientId);
                        }
                    }
                }
                // requested clean session
                else
                {
                    // send CONNACK message to the client
                    MqttOutgoingMessageManager.Connack(clientConnection, message, returnCode, clientId, false);

                    MqttSessionManager.ClearSession(clientId);
                }
            }
            else
            {
                // send CONNACK message to the client
                MqttOutgoingMessageManager.Connack(clientConnection, message, returnCode, clientId, false);
            }
        }
 public void EnqueueApplicationMessage(MqttClientSession senderClientSession, MqttPublishPacket publishPacket)
 {
     throw new NotSupportedException();
 }
Beispiel #21
0
 protected abstract Task <MqttMessage> ProcessAsync(MqttClientSession clientSession, TPacket packet);
Beispiel #22
0
 protected override Task <MqttMessage> ProcessAsync(MqttClientSession clientSession, SubscribePacket packet)
 {
     //TODO:处理订阅话题的逻辑和转发请求
     _logger.LogDebug("recieve SubscribePacket message");
     return(Task.FromResult(MqttMessage.SUCCESS));
 }
Beispiel #23
0
 public MqttEnqueuedMessage(MqttClientSession sender, MqttPublishPacket publishPacket)
 {
     Sender        = sender;
     PublishPacket = publishPacket;
 }
Beispiel #24
0
 public Task <MqttMessage> ProcessAsync(MqttClientSession clientSession, Packet packet)
 {
     throw new System.NotImplementedException();
 }