package io.moquette.spi.impl; import io.moquette.parser.proto.messages.PublishMessage; import io.moquette.server.ConnectionDescriptor; import io.moquette.server.netty.NettyUtils; import io.moquette.spi.IMessagesStore; import io.moquette.spi.ISessionsStore; import io.moquette.spi.impl.subscriptions.Subscription; import io.moquette.spi.impl.subscriptions.SubscriptionsStore; import io.moquette.spi.security.IAuthorizator; import io.netty.channel.Channel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; import java.util.concurrent.ConcurrentMap; import static io.moquette.spi.impl.ProtocolProcessor.asStoredMessage; class Qos0PublishHandler { private static final Logger LOG = LoggerFactory.getLogger(Qos0PublishHandler.class); private final IAuthorizator m_authorizator; private final SubscriptionsStore subscriptions; private final IMessagesStore m_messagesStore; private final BrokerInterceptor m_interceptor; private final MessagesPublisher metaPublisher; public Qos0PublishHandler(IAuthorizator authorizator, SubscriptionsStore subscriptions, IMessagesStore messagesStore, BrokerInterceptor interceptor, ConcurrentMap connectionDescriptors, ISessionsStore sessionsStore) { this.m_authorizator = authorizator; this.subscriptions = subscriptions; this.m_messagesStore = messagesStore; this.m_interceptor = interceptor; this.metaPublisher = new MessagesPublisher(connectionDescriptors, sessionsStore, messagesStore); } void receivedPublishQos0(Channel channel, PublishMessage msg) { //verify if topic can be write final String topic = msg.getTopicName(); if (checkWriteOnTopic(topic, channel)) { return; } //route message to subscribers IMessagesStore.StoredMessage toStoreMsg = asStoredMessage(msg); String clientID = NettyUtils.clientID(channel); toStoreMsg.setClientID(clientID); LOG.debug("publish2Subscribers republishing to existing subscribers that matches the topic {}", topic); if (LOG.isTraceEnabled()) { LOG.trace("content <{}>", DebugUtils.payload2Str(toStoreMsg.getMessage())); LOG.trace("subscription tree {}", subscriptions.dumpTree()); } List topicMatchingSubscriptions = subscriptions.matches(topic); this.metaPublisher.publish2Subscribers(toStoreMsg, topicMatchingSubscriptions); if (msg.isRetainFlag()) { //QoS == 0 && retain => clean old retained m_messagesStore.cleanRetained(topic); } String username = NettyUtils.userName(channel); m_interceptor.notifyTopicPublished(msg, clientID, username); } boolean checkWriteOnTopic(String topic, Channel channel) { String clientID = NettyUtils.clientID(channel); String username = NettyUtils.userName(channel); if (!m_authorizator.canWrite(topic, username, clientID)) { LOG.debug("topic {} doesn't have write credentials", topic); return true; } return false; } }