public void disconnect(String clientID) { final Session session = retrieve(clientID); if (session == null) { LOG.debug("Some other thread already removed the session CId={}", clientID); return; } session.disconnect(); }
public void writabilityChanged() { if (channel.isWritable()) { LOG.debug("Channel {} is again writable", channel); final Session session = sessionRegistry.retrieve(getClientId()); session.writabilityChanged(); } }
public void resendNotAckedPublishes() { final Session session = sessionRegistry.retrieve(getClientId()); session.resendInflightNotAcked(); }
private void processPubComp(MqttMessage msg) { final int messageID = ((MqttMessageIdVariableHeader) msg.variableHeader()).messageId(); final Session session = sessionRegistry.retrieve(getClientId()); session.processPubComp(messageID); }
private void processPubRec(MqttMessage msg) { final int messageID = ((MqttMessageIdVariableHeader) msg.variableHeader()).messageId(); final Session session = sessionRegistry.retrieve(getClientId()); session.processPubRec(messageID); }
private void processPubAck(MqttMessage msg) { final int messageID = ((MqttMessageIdVariableHeader) msg.variableHeader()).messageId(); Session session = sessionRegistry.retrieve(getClientId()); session.pubAckReceived(messageID); }
private void processPubRel(MqttMessage msg) { final Session session = sessionRegistry.retrieve(getClientId()); final int messageID = ((MqttMessageIdVariableHeader) msg.variableHeader()).messageId(); session.receivedPubRelQos2(messageID); sendPubCompMessage(messageID); }
void handleConnectionLost() { String clientID = NettyUtils.clientID(channel); if (clientID == null || clientID.isEmpty()) { return; } LOG.info("Notifying connection lost event. CId: {}, channel: {}", clientID, channel); Session session = sessionRegistry.retrieve(clientID); if (session.hasWill()) { postOffice.fireWill(session.getWill()); } if (session.isClean()) { sessionRegistry.remove(clientID); } else { sessionRegistry.disconnect(clientID); } connected = false; //dispatch connection lost to intercept. String userName = NettyUtils.userName(channel); postOffice.dispatchConnectionLost(clientID,userName); LOG.trace("dispatch disconnection: clientId={}, userName={}", clientID, userName); }
private void publishRetainedMessagesForSubscriptions(String clientID, List<Subscription> newSubscriptions) { Session targetSession = this.sessionRegistry.retrieve(clientID); for (Subscription subscription : newSubscriptions) { final String topicFilter = subscription.getTopicFilter().toString(); final List<RetainedMessage> retainedMsgs = retainedRepository.retainedOnTopic(topicFilter); if (retainedMsgs.isEmpty()) { // not found continue; } for (RetainedMessage retainedMsg : retainedMsgs) { final MqttQoS retainedQos = retainedMsg.qosLevel(); MqttQoS qos = lowerQosToTheSubscriptionDesired(subscription, retainedQos); // final ByteBuf origPayload = retainedMsg.getPayload(); final ByteBuf payloadBuf = Unpooled.wrappedBuffer(retainedMsg.getPayload()); // ByteBuf payload = origPayload.retainedDuplicate(); targetSession.sendRetainedPublishOnSessionAtQos(subscription.getTopicFilter(), qos, payloadBuf); } } }
public void subscribeClientToTopics(MqttSubscribeMessage msg, String clientID, String username, MQTTConnection mqttConnection) { // verify which topics of the subscribe ongoing has read access permission int messageID = messageId(msg); List<MqttTopicSubscription> ackTopics = authorizator.verifyTopicsReadAccess(clientID, username, msg); MqttSubAckMessage ackMessage = doAckMessageFromValidateFilters(ackTopics, messageID); // store topics subscriptions in session List<Subscription> newSubscriptions = ackTopics.stream() .filter(req -> req.qualityOfService() != FAILURE) .map(req -> { final Topic topic = new Topic(req.topicName()); return new Subscription(clientID, topic, req.qualityOfService()); }).collect(Collectors.toList()); for (Subscription subscription : newSubscriptions) { subscriptions.add(subscription); } // add the subscriptions to Session Session session = sessionRegistry.retrieve(clientID); session.addSubscriptions(newSubscriptions); // send ack message mqttConnection.sendSubAckMessage(messageID, ackMessage); publishRetainedMessagesForSubscriptions(clientID, newSubscriptions); for (Subscription subscription : newSubscriptions) { interceptor.notifyTopicSubscribed(subscription, username); } }
private void publish2Subscribers(ByteBuf origPayload, Topic topic, MqttQoS publishingQos) { Set<Subscription> topicMatchingSubscriptions = subscriptions.matchQosSharpening(topic); for (final Subscription sub : topicMatchingSubscriptions) { MqttQoS qos = lowerQosToTheSubscriptionDesired(sub, publishingQos); Session targetSession = this.sessionRegistry.retrieve(sub.getClientId()); boolean isSessionPresent = targetSession != null; if (isSessionPresent) { LOG.debug("Sending PUBLISH message to active subscriber CId: {}, topicFilter: {}, qos: {}", sub.getClientId(), sub.getTopicFilter(), qos); // final String login = targetSession.login(); // if (!authorizator.canRead(topic, login, sub.getClientId())) { // LOG.debug("Authorizator prohibit Client {} to be notified on {}", sub.getClientId(), topic); // return; // } // we need to retain because duplicate only copy r/w indexes and don't retain() causing refCnt = 0 ByteBuf payload = origPayload.retainedDuplicate(); targetSession.sendPublishOnSessionAtQos(topic, qos, payload); } else { // If we are, the subscriber disconnected after the subscriptions tree selected that session as a // destination. LOG.debug("PUBLISH to not yet present session. CId: {}, topicFilter: {}, qos: {}", sub.getClientId(), sub.getTopicFilter(), qos); } } }
final Session session = sessionRegistry.retrieve(clientId); session.receivedPublishQos2(messageID, msg); postOffice.receivedPublishQos2(this, msg, username);
@Test public void testZeroByteClientIdWithCleanSession() { // Connect message with clean session set to true and client id is null. MqttConnectMessage msg = MqttMessageBuilders.connect() .protocolVersion(MqttVersion.MQTT_3_1_1) .clientId(null) .cleanSession(true) .build(); sut.processConnect(msg); assertEqualsConnAck("Connection must be accepted", CONNECTION_ACCEPTED, channel.readOutbound()); assertNotNull("unique clientid must be generated", sut.getClientId()); assertTrue("clean session flag must be true", sessionRegistry.retrieve(sut.getClientId()).isClean()); assertTrue("Connection must be open", channel.isOpen()); }
@Test public void connectWithCleanSessionUpdateClientSession() { // first connect with clean session true MqttConnectMessage msg = connMsg.clientId(FAKE_CLIENT_ID).cleanSession(true).build(); connection.processConnect(msg); assertEqualsConnAck(CONNECTION_ACCEPTED, channel.readOutbound()); connection.processDisconnect(null); assertFalse(channel.isOpen()); // second connect with clean session false EmbeddedChannel anotherChannel = new EmbeddedChannel(); MQTTConnection anotherConnection = createMQTTConnection(ALLOW_ANONYMOUS_AND_ZEROBYTE_CLIENT_ID, anotherChannel); MqttConnectMessage secondConnMsg = MqttMessageBuilders.connect() .clientId(FAKE_CLIENT_ID) .protocolVersion(MqttVersion.MQTT_3_1) .build(); anotherConnection.processConnect(secondConnMsg); assertEqualsConnAck(CONNECTION_ACCEPTED, anotherChannel.readOutbound()); // Verify client session is clean false Session session = sut.retrieve(FAKE_CLIENT_ID); assertFalse(session.isClean()); } }