/// <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); } }
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)); }
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 }); }
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); }
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); }
/// <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); } } }
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); }
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); }
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); } }
public MqttSessionStatus(MqttClientSession session, MqttClientSessionsManager sessionsManager) { _session = session ?? throw new ArgumentNullException(nameof(session)); _sessionsManager = sessionsManager ?? throw new ArgumentNullException(nameof(sessionsManager)); }
public void CleanSession() { session.Clear(); session = new MqttClientSession(clientId); }
public MqttSessionManager(string clientId) { this.clientId = clientId; session = new MqttClientSession(clientId); }
public Task <MqttMessage> ProcessAsync(MqttClientSession clientSession, Packet packet) { return(Task.FromResult(PingAckMsg)); }
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(); }
protected abstract Task <MqttMessage> ProcessAsync(MqttClientSession clientSession, TPacket packet);
protected override Task <MqttMessage> ProcessAsync(MqttClientSession clientSession, SubscribePacket packet) { //TODO:处理订阅话题的逻辑和转发请求 _logger.LogDebug("recieve SubscribePacket message"); return(Task.FromResult(MqttMessage.SUCCESS)); }
public MqttEnqueuedMessage(MqttClientSession sender, MqttPublishPacket publishPacket) { Sender = sender; PublishPacket = publishPacket; }
public Task <MqttMessage> ProcessAsync(MqttClientSession clientSession, Packet packet) { throw new System.NotImplementedException(); }