Moved avay from ConnectionDescriptorStore unused methods and stuff that hasn't nothing about ConnectionDescriptor storing

This commit is contained in:
andsel
2018-04-27 20:16:11 +02:00
parent 99f0612209
commit 6bbeba1612
9 changed files with 132 additions and 168 deletions
@@ -16,10 +16,13 @@
package io.moquette.connections; package io.moquette.connections;
import io.moquette.server.ConnectionDescriptor;
import java.util.Collection; import java.util.Collection;
import java.util.Optional;
/** /**
* This interface will be used by an external codebase to retrieve and close physical connections. * Repository for active connections
*/ */
public interface IConnectionsManager { public interface IConnectionsManager {
@@ -28,7 +31,15 @@ public interface IConnectionsManager {
* *
* @return * @return
*/ */
int getActiveConnectionsNo(); int countActiveConnections();
Optional<ConnectionDescriptor> lookupDescriptor(String clientID);
ConnectionDescriptor addConnection(ConnectionDescriptor descriptor);
boolean removeConnection(ConnectionDescriptor descriptor);
ConnectionDescriptor getConnection(String clientID);
/** /**
* Determines wether a MQTT client is connected to the broker. * Determines wether a MQTT client is connected to the broker.
@@ -44,21 +55,4 @@ public interface IConnectionsManager {
* @return * @return
*/ */
Collection<String> getConnectedClientIds(); Collection<String> getConnectedClientIds();
/**
* Closes a physical connection.
*
* @param clientID
* @param closeImmediately
* If false, the connection will be flushed before it is closed.
* @return
*/
boolean closeConnection(String clientID, boolean closeImmediately);
/**
* Returns the state of all the sessions
*
* @return
*/
Collection<MqttSession> getSessions();
} }
@@ -69,19 +69,6 @@ public class ConnectionDescriptor {
this.channel.writeAndFlush(payload).addListener(FIRE_EXCEPTION_ON_FAILURE); this.channel.writeAndFlush(payload).addListener(FIRE_EXCEPTION_ON_FAILURE);
} }
public void setupAutoFlusher(int flushIntervalMs) {
try {
this.channel.pipeline().addAfter(
"idleEventHandler",
"autoFlusher",
new AutoFlushHandler(flushIntervalMs, TimeUnit.MILLISECONDS));
} catch (NoSuchElementException nseex) {
// the idleEventHandler is not present on the pipeline
this.channel.pipeline()
.addFirst("autoFlusher", new AutoFlushHandler(flushIntervalMs, TimeUnit.MILLISECONDS));
}
}
public boolean doesNotUseChannel(Channel channel) { public boolean doesNotUseChannel(Channel channel) {
return !(this.channel.equals(channel)); return !(this.channel.equals(channel));
} }
@@ -17,21 +17,11 @@
package io.moquette.server; package io.moquette.server;
import io.moquette.connections.IConnectionsManager; import io.moquette.connections.IConnectionsManager;
import io.moquette.connections.MqttConnectionMetrics;
import io.moquette.connections.MqttSession;
import io.moquette.connections.MqttSubscription;
import io.moquette.server.netty.metrics.BytesMetrics;
import io.moquette.server.netty.metrics.MessageMetrics;
import io.moquette.spi.ClientSession;
import io.moquette.spi.impl.SessionsRepository;
import io.moquette.spi.impl.subscriptions.Subscription;
import io.netty.handler.codec.mqtt.MqttMessage;
import io.netty.handler.codec.mqtt.MqttMessageType;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
@@ -40,56 +30,39 @@ public class ConnectionDescriptorStore implements IConnectionsManager {
private static final Logger LOG = LoggerFactory.getLogger(ConnectionDescriptorStore.class); private static final Logger LOG = LoggerFactory.getLogger(ConnectionDescriptorStore.class);
private final ConcurrentMap<String, ConnectionDescriptor> connectionDescriptors; private final ConcurrentMap<String, ConnectionDescriptor> connectionDescriptors;
private final SessionsRepository sessionsRepository;
public ConnectionDescriptorStore(SessionsRepository sessionsRepository) { public ConnectionDescriptorStore() {
this.connectionDescriptors = new ConcurrentHashMap<>(); this.connectionDescriptors = new ConcurrentHashMap<>();
this.sessionsRepository = sessionsRepository;
} }
public boolean sendMessage(MqttMessage message, Integer messageID, String clientID) { @Override
final MqttMessageType messageType = message.fixedHeader().messageType(); public Optional<ConnectionDescriptor> lookupDescriptor(String clientID) {
try { if (clientID == null) {
if (messageID != null) { return Optional.empty();
LOG.info("Sending {} message CId=<{}>, messageId={}", messageType, clientID, messageID);
} else {
LOG.debug("Sending {} message CId=<{}>", messageType, clientID);
}
ConnectionDescriptor descriptor = connectionDescriptors.get(clientID);
if (descriptor == null) {
if (messageID != null) {
LOG.error("Client has just disconnected. {} message could not be sent. CId=<{}>, messageId={}",
messageType, clientID, messageID);
} else {
LOG.error("Client has just disconnected. {} could not be sent. CId=<{}>", messageType, clientID);
}
/*
* If the client has just disconnected, its connection descriptor will be null. We
* don't have to make the broker crash: we'll just discard the PUBACK message.
*/
return false;
}
descriptor.writeAndFlush(message);
return true;
} catch (Throwable e) {
String errorMsg = "Unable to send " + messageType + " message. CId=<" + clientID + ">";
if (messageID != null) {
errorMsg += ", messageId=" + messageID;
}
LOG.error(errorMsg, e);
return false;
} }
ConnectionDescriptor descriptor = connectionDescriptors.get(clientID);
if (descriptor == null) {
/*
* If the client has just disconnected, its connection descriptor will be null. We
* don't have to make the broker crash: we'll just discard the PUBACK message.
*/
return Optional.empty();
}
return Optional.of(descriptor);
} }
@Override
public ConnectionDescriptor addConnection(ConnectionDescriptor descriptor) { public ConnectionDescriptor addConnection(ConnectionDescriptor descriptor) {
return connectionDescriptors.putIfAbsent(descriptor.clientID, descriptor); return connectionDescriptors.putIfAbsent(descriptor.clientID, descriptor);
} }
@Override
public boolean removeConnection(ConnectionDescriptor descriptor) { public boolean removeConnection(ConnectionDescriptor descriptor) {
return connectionDescriptors.remove(descriptor.clientID, descriptor); return connectionDescriptors.remove(descriptor.clientID, descriptor);
} }
@Override
public ConnectionDescriptor getConnection(String clientID) { public ConnectionDescriptor getConnection(String clientID) {
return connectionDescriptors.get(clientID); return connectionDescriptors.get(clientID);
} }
@@ -100,7 +73,7 @@ public class ConnectionDescriptorStore implements IConnectionsManager {
} }
@Override @Override
public int getActiveConnectionsNo() { public int countActiveConnections() {
return connectionDescriptors.size(); return connectionDescriptors.size();
} }
@@ -108,56 +81,4 @@ public class ConnectionDescriptorStore implements IConnectionsManager {
public Collection<String> getConnectedClientIds() { public Collection<String> getConnectedClientIds() {
return connectionDescriptors.keySet(); return connectionDescriptors.keySet();
} }
@Override
public boolean closeConnection(String clientID, boolean closeImmediately) {
ConnectionDescriptor descriptor = connectionDescriptors.get(clientID);
if (descriptor == null) {
LOG.error("Connection descriptor doesn't exist. MQTT connection cannot be closed. CId=<{}>, " +
"closeImmediately={}", clientID, closeImmediately);
return false;
}
if (closeImmediately) {
descriptor.abort();
return true;
} else {
return descriptor.close();
}
}
@Override
public Collection<MqttSession> getSessions() {
LOG.info("Retrieving status of all sessions.");
Collection<MqttSession> result = new ArrayList<>();
for (ClientSession session : this.sessionsRepository.getAllSessions()) {
result.add(buildMqttSession(session));
}
return result;
}
private MqttSession buildMqttSession(ClientSession session) {
MqttSession result = new MqttSession();
Collection<MqttSubscription> mqttSubscriptions = new ArrayList<>();
for (Subscription subscription : session.getSubscriptions()) {
mqttSubscriptions.add(new MqttSubscription(subscription.getRequestedQos().toString(),
subscription.getClientId(), subscription.getTopicFilter().toString(), subscription.isActive()));
}
result.setActiveSubscriptions(mqttSubscriptions);
result.setCleanSession(session.isCleanSession());
ConnectionDescriptor descriptor = this.getConnection(session.clientID);
if (descriptor != null) {
result.setConnectionEstablished(true);
BytesMetrics bytesMetrics = descriptor.getBytesMetrics();
MessageMetrics messageMetrics = descriptor.getMessageMetrics();
result.setConnectionMetrics(new MqttConnectionMetrics(bytesMetrics.readBytes(), bytesMetrics.wroteBytes(),
messageMetrics.messagesRead(), messageMetrics.messagesWrote()));
} else {
result.setConnectionEstablished(false);
}
result.setPendingPublishMessagesNo(session.getPendingPublishMessagesNo());
result.setSecondPhaseAckPendingMessages(session.countPubReleaseWaitingPubComplete());
result.setInflightMessages(session.getInflightMessagesNo());
return result;
}
} }
@@ -16,7 +16,7 @@
package io.moquette.spi.impl; package io.moquette.spi.impl;
import io.moquette.server.ConnectionDescriptorStore; import io.moquette.connections.IConnectionsManager;
import io.moquette.spi.ClientSession; import io.moquette.spi.ClientSession;
import io.moquette.spi.IMessagesStore; import io.moquette.spi.IMessagesStore;
import io.moquette.spi.impl.subscriptions.ISubscriptionsDirectory; import io.moquette.spi.impl.subscriptions.ISubscriptionsDirectory;
@@ -34,21 +34,21 @@ import static io.moquette.spi.impl.ProtocolProcessor.lowerQosToTheSubscriptionDe
class MessagesPublisher { class MessagesPublisher {
private static final Logger LOG = LoggerFactory.getLogger(MessagesPublisher.class); private static final Logger LOG = LoggerFactory.getLogger(MessagesPublisher.class);
private final ConnectionDescriptorStore connectionDescriptors; private final IConnectionsManager connectionDescriptors;
private final PersistentQueueMessageSender messageSender; private final PersistentQueueMessageSender messageSender;
private final ISubscriptionsDirectory subscriptions; private final ISubscriptionsDirectory subscriptions;
private SessionsRepository sessionsRepository; private SessionsRepository sessionsRepository;
public MessagesPublisher(ConnectionDescriptorStore connectionDescriptors, MessagesPublisher(IConnectionsManager connectionDescriptors,
PersistentQueueMessageSender messageSender, ISubscriptionsDirectory subscriptions, PersistentQueueMessageSender messageSender, ISubscriptionsDirectory subscriptions,
SessionsRepository sessionsRepository) { SessionsRepository sessionsRepository) {
this.connectionDescriptors = connectionDescriptors; this.connectionDescriptors = connectionDescriptors;
this.messageSender = messageSender; this.messageSender = messageSender;
this.subscriptions = subscriptions; this.subscriptions = subscriptions;
this.sessionsRepository = sessionsRepository; this.sessionsRepository = sessionsRepository;
} }
static MqttPublishMessage notRetainedPublish(String topic, MqttQoS qos, ByteBuf message) { private static MqttPublishMessage notRetainedPublish(String topic, MqttQoS qos, ByteBuf message) {
return notRetainedPublishWithMessageId(topic, qos, message, 0); return notRetainedPublishWithMessageId(topic, qos, message, 0);
} }
@@ -16,21 +16,27 @@
package io.moquette.spi.impl; package io.moquette.spi.impl;
import io.moquette.connections.IConnectionsManager;
import io.moquette.server.ConnectionDescriptor;
import io.moquette.server.ConnectionDescriptorStore; import io.moquette.server.ConnectionDescriptorStore;
import io.moquette.spi.ClientSession; import io.moquette.spi.ClientSession;
import io.netty.handler.codec.mqtt.MqttMessageType;
import io.netty.handler.codec.mqtt.MqttPublishMessage; import io.netty.handler.codec.mqtt.MqttPublishMessage;
import io.netty.handler.codec.mqtt.MqttQoS; import io.netty.handler.codec.mqtt.MqttQoS;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Optional;
import static io.moquette.spi.impl.ProtocolProcessor.asStoredMessage; import static io.moquette.spi.impl.ProtocolProcessor.asStoredMessage;
import static io.netty.handler.codec.mqtt.MqttQoS.AT_MOST_ONCE; import static io.netty.handler.codec.mqtt.MqttQoS.AT_MOST_ONCE;
class PersistentQueueMessageSender { class PersistentQueueMessageSender {
private static final Logger LOG = LoggerFactory.getLogger(PersistentQueueMessageSender.class); private static final Logger LOG = LoggerFactory.getLogger(PersistentQueueMessageSender.class);
private final ConnectionDescriptorStore connectionDescriptorStore; private final IConnectionsManager connectionDescriptorStore;
PersistentQueueMessageSender(ConnectionDescriptorStore connectionDescriptorStore) { PersistentQueueMessageSender(IConnectionsManager connectionDescriptorStore) {
this.connectionDescriptorStore = connectionDescriptorStore; this.connectionDescriptorStore = connectionDescriptorStore;
} }
@@ -46,7 +52,19 @@ class PersistentQueueMessageSender {
LOG.info("Sending PUBLISH message. MessageId={}, CId={}, topic={}", messageId, clientId, topicName); LOG.info("Sending PUBLISH message. MessageId={}, CId={}, topic={}", messageId, clientId, topicName);
} }
boolean messageDelivered = connectionDescriptorStore.sendMessage(pubMessage, messageId, clientId); boolean messageDelivered = false;
final Optional<ConnectionDescriptor> optDescriptor = connectionDescriptorStore.lookupDescriptor(clientId);
if (optDescriptor.isPresent()) {
final ConnectionDescriptor descriptor = optDescriptor.get();
try {
descriptor.writeAndFlush(pubMessage);
messageDelivered = true;
} catch (Throwable e) {
LOG.error("Unable to send {} message. CId=<{}>, messageId={}", pubMessage.fixedHeader().messageType(),
clientId, messageId, e);
}
}
if (!messageDelivered) { if (!messageDelivered) {
if (qos != AT_MOST_ONCE && !clientsession.isCleanSession()) { if (qos != AT_MOST_ONCE && !clientsession.isCleanSession()) {
@@ -16,10 +16,12 @@
package io.moquette.spi.impl; package io.moquette.spi.impl;
import io.moquette.connections.IConnectionsManager;
import io.moquette.interception.InterceptHandler; import io.moquette.interception.InterceptHandler;
import io.moquette.interception.messages.InterceptAcknowledgedMessage; import io.moquette.interception.messages.InterceptAcknowledgedMessage;
import io.moquette.server.ConnectionDescriptor; import io.moquette.server.ConnectionDescriptor;
import io.moquette.server.ConnectionDescriptorStore; import io.moquette.server.ConnectionDescriptorStore;
import io.moquette.server.netty.AutoFlushHandler;
import io.moquette.server.netty.NettyUtils; import io.moquette.server.netty.NettyUtils;
import io.moquette.spi.*; import io.moquette.spi.*;
import io.moquette.spi.IMessagesStore.StoredMessage; import io.moquette.spi.IMessagesStore.StoredMessage;
@@ -41,6 +43,7 @@ import java.nio.charset.StandardCharsets;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import static io.moquette.server.ConnectionDescriptor.ConnectionState.*; import static io.moquette.server.ConnectionDescriptor.ConnectionState.*;
import static io.moquette.spi.impl.InternalRepublisher.createPublishForQos; import static io.moquette.spi.impl.InternalRepublisher.createPublishForQos;
@@ -97,11 +100,11 @@ public class ProtocolProcessor {
private static final Logger LOG = LoggerFactory.getLogger(ProtocolProcessor.class); private static final Logger LOG = LoggerFactory.getLogger(ProtocolProcessor.class);
private ConnectionDescriptorStore connectionDescriptors; private IConnectionsManager connectionDescriptors;
private ConcurrentMap<RunningSubscription, SubscriptionState> subscriptionInCourse; private ConcurrentMap<RunningSubscription, SubscriptionState> subscriptionInCourse;
private ISubscriptionsDirectory subscriptions; private ISubscriptionsDirectory subscriptions;
private ISubscriptionsStore subscriptionStore; // private ISubscriptionsStore subscriptionStore;
private boolean allowAnonymous; private boolean allowAnonymous;
private boolean allowZeroByteClientId; private boolean allowZeroByteClientId;
private IAuthorizator m_authorizator; private IAuthorizator m_authorizator;
@@ -136,7 +139,7 @@ public class ProtocolProcessor {
public void init(ISubscriptionsDirectory subscriptions, IMessagesStore storageService, ISessionsStore sessionsStore, public void init(ISubscriptionsDirectory subscriptions, IMessagesStore storageService, ISessionsStore sessionsStore,
IAuthenticator authenticator, boolean allowAnonymous, boolean allowZeroByteClientId, IAuthenticator authenticator, boolean allowAnonymous, boolean allowZeroByteClientId,
IAuthorizator authorizator, BrokerInterceptor interceptor, SessionsRepository sessionsRepository) { IAuthorizator authorizator, BrokerInterceptor interceptor, SessionsRepository sessionsRepository) {
init(new ConnectionDescriptorStore(sessionsRepository), subscriptions, storageService, sessionsStore, init(new ConnectionDescriptorStore(), subscriptions, storageService, sessionsStore,
authenticator, allowAnonymous, allowZeroByteClientId, authorizator, interceptor, sessionsRepository); authenticator, allowAnonymous, allowZeroByteClientId, authorizator, interceptor, sessionsRepository);
} }
@@ -158,11 +161,11 @@ public class ProtocolProcessor {
* @param interceptor * @param interceptor
* to notify events to an intercept handler * to notify events to an intercept handler
*/ */
void init(ConnectionDescriptorStore connectionDescriptors, ISubscriptionsDirectory subscriptions, void init(IConnectionsManager connectionDescriptors, ISubscriptionsDirectory subscriptions,
IMessagesStore storageService, ISessionsStore sessionsStore, IAuthenticator authenticator, IMessagesStore storageService, ISessionsStore sessionsStore, IAuthenticator authenticator,
boolean allowAnonymous, boolean allowZeroByteClientId, IAuthorizator authorizator, boolean allowAnonymous, boolean allowZeroByteClientId, IAuthorizator authorizator,
BrokerInterceptor interceptor, SessionsRepository sessionsRepository) { BrokerInterceptor interceptor, SessionsRepository sessionsRepository) {
LOG.info("Initializing MQTT protocol processor..."); LOG.debug("Initializing MQTT protocol processor...");
this.connectionDescriptors = connectionDescriptors; this.connectionDescriptors = connectionDescriptors;
this.subscriptionInCourse = new ConcurrentHashMap<>(); this.subscriptionInCourse = new ConcurrentHashMap<>();
this.m_interceptor = interceptor; this.m_interceptor = interceptor;
@@ -176,7 +179,6 @@ public class ProtocolProcessor {
m_authenticator = authenticator; m_authenticator = authenticator;
m_messagesStore = storageService; m_messagesStore = storageService;
m_sessionsStore = sessionsStore; m_sessionsStore = sessionsStore;
subscriptionStore = sessionsStore.subscriptionStore();
this.sessionsRepository = sessionsRepository; this.sessionsRepository = sessionsRepository;
@@ -185,7 +187,7 @@ public class ProtocolProcessor {
this.messagesPublisher = new MessagesPublisher(connectionDescriptors, messageSender, this.messagesPublisher = new MessagesPublisher(connectionDescriptors, messageSender,
subscriptions, this.sessionsRepository); subscriptions, this.sessionsRepository);
LOG.info("Initializing QoS publish handlers..."); LOG.debug("Initializing QoS publish handlers...");
this.qos0PublishHandler = new Qos0PublishHandler(m_authorizator, m_messagesStore, m_interceptor, this.qos0PublishHandler = new Qos0PublishHandler(m_authorizator, m_messagesStore, m_interceptor,
this.messagesPublisher); this.messagesPublisher);
this.qos1PublishHandler = new Qos1PublishHandler(m_authorizator, m_messagesStore, m_interceptor, this.qos1PublishHandler = new Qos1PublishHandler(m_authorizator, m_messagesStore, m_interceptor,
@@ -193,7 +195,7 @@ public class ProtocolProcessor {
this.qos2PublishHandler = new Qos2PublishHandler(m_authorizator, subscriptions, m_messagesStore, m_interceptor, this.qos2PublishHandler = new Qos2PublishHandler(m_authorizator, subscriptions, m_messagesStore, m_interceptor,
this.connectionDescriptors, this.messagesPublisher, this.sessionsRepository); this.connectionDescriptors, this.messagesPublisher, this.sessionsRepository);
LOG.info("Initializing internal republisher..."); LOG.debug("Initializing internal republisher...");
this.internalRepublisher = new InternalRepublisher(messageSender); this.internalRepublisher = new InternalRepublisher(messageSender);
} }
@@ -263,6 +265,10 @@ public class ProtocolProcessor {
channel.close().addListener(CLOSE_ON_FAILURE); channel.close().addListener(CLOSE_ON_FAILURE);
return; return;
} }
int flushIntervalMs = 500/* (keepAlive * 1000) / 2 */;
setupAutoFlusher(channel, flushIntervalMs);
final boolean success = descriptor.assignState(MESSAGES_REPUBLISHED, ESTABLISHED); final boolean success = descriptor.assignState(MESSAGES_REPUBLISHED, ESTABLISHED);
if (!success) { if (!success) {
channel.close().addListener(CLOSE_ON_FAILURE); channel.close().addListener(CLOSE_ON_FAILURE);
@@ -271,6 +277,19 @@ public class ProtocolProcessor {
LOG.info("Connected client <{}> with login <{}>", clientId, payload.userName()); LOG.info("Connected client <{}> with login <{}>", clientId, payload.userName());
} }
private void setupAutoFlusher(Channel channel, int flushIntervalMs) {
try {
channel.pipeline().addAfter(
"idleEventHandler",
"autoFlusher",
new AutoFlushHandler(flushIntervalMs, TimeUnit.MILLISECONDS));
} catch (NoSuchElementException nseex) {
// the idleEventHandler is not present on the pipeline
channel.pipeline()
.addFirst("autoFlusher", new AutoFlushHandler(flushIntervalMs, TimeUnit.MILLISECONDS));
}
}
private MqttConnAckMessage connAck(MqttConnectReturnCode returnCode) { private MqttConnAckMessage connAck(MqttConnectReturnCode returnCode) {
return connAck(returnCode, false); return connAck(returnCode, false);
} }
@@ -379,8 +398,6 @@ public class ProtocolProcessor {
LOG.info("Republishing stored publish events. CId={}", clientSession.clientID); LOG.info("Republishing stored publish events. CId={}", clientSession.clientID);
this.internalRepublisher.publishStored(clientSession); this.internalRepublisher.publishStored(clientSession);
} }
int flushIntervalMs = 500/* (keepAlive * 1000) / 2 */;
descriptor.setupAutoFlusher(flushIntervalMs);
return true; return true;
} }
@@ -165,7 +165,7 @@ public class ProtocolProcessorBootstrapper {
} }
LOG.info("Initializing connection descriptor store..."); LOG.info("Initializing connection descriptor store...");
connectionDescriptors = new ConnectionDescriptorStore(sessionsRepository); connectionDescriptors = new ConnectionDescriptorStore();
LOG.info("Initializing MQTT protocol processor..."); LOG.info("Initializing MQTT protocol processor...");
boolean allowAnonymous = Boolean boolean allowAnonymous = Boolean
@@ -16,6 +16,8 @@
package io.moquette.spi.impl; package io.moquette.spi.impl;
import io.moquette.connections.IConnectionsManager;
import io.moquette.server.ConnectionDescriptor;
import io.moquette.server.ConnectionDescriptorStore; import io.moquette.server.ConnectionDescriptorStore;
import io.moquette.server.netty.NettyUtils; import io.moquette.server.netty.NettyUtils;
import io.moquette.spi.IMessagesStore; import io.moquette.spi.IMessagesStore;
@@ -29,6 +31,8 @@ import io.netty.handler.codec.mqtt.MqttPublishMessage;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Optional;
import static io.moquette.spi.impl.ProtocolProcessor.asStoredMessage; import static io.moquette.spi.impl.ProtocolProcessor.asStoredMessage;
import static io.netty.handler.codec.mqtt.MqttMessageIdVariableHeader.from; import static io.netty.handler.codec.mqtt.MqttMessageIdVariableHeader.from;
import static io.netty.handler.codec.mqtt.MqttQoS.AT_MOST_ONCE; import static io.netty.handler.codec.mqtt.MqttQoS.AT_MOST_ONCE;
@@ -39,11 +43,11 @@ class Qos1PublishHandler extends QosPublishHandler {
private final IMessagesStore m_messagesStore; private final IMessagesStore m_messagesStore;
private final BrokerInterceptor m_interceptor; private final BrokerInterceptor m_interceptor;
private final ConnectionDescriptorStore connectionDescriptors; private final IConnectionsManager connectionDescriptors;
private final MessagesPublisher publisher; private final MessagesPublisher publisher;
public Qos1PublishHandler(IAuthorizator authorizator, IMessagesStore messagesStore, BrokerInterceptor interceptor, Qos1PublishHandler(IAuthorizator authorizator, IMessagesStore messagesStore, BrokerInterceptor interceptor,
ConnectionDescriptorStore connectionDescriptors, MessagesPublisher messagesPublisher) { IConnectionsManager connectionDescriptors, MessagesPublisher messagesPublisher) {
super(authorizator); super(authorizator);
this.m_messagesStore = messagesStore; this.m_messagesStore = messagesStore;
this.m_interceptor = interceptor; this.m_interceptor = interceptor;
@@ -89,16 +93,17 @@ class Qos1PublishHandler extends QosPublishHandler {
MqttPubAckMessage pubAckMessage = new MqttPubAckMessage(fixedHeader, from(messageID)); MqttPubAckMessage pubAckMessage = new MqttPubAckMessage(fixedHeader, from(messageID));
try { try {
if (connectionDescriptors == null) {
throw new RuntimeException("Internal bad error, found connectionDescriptors to null while it should " +
"be initialized, somewhere it's overwritten!!");
}
LOG.trace("connected clientIDs are {}", connectionDescriptors.getConnectedClientIds()); LOG.trace("connected clientIDs are {}", connectionDescriptors.getConnectedClientIds());
if (!connectionDescriptors.isConnected(clientId)) { if (!connectionDescriptors.isConnected(clientId)) {
throw new RuntimeException(String.format("Can't find a ConnectionDescriptor for client %s in cache %s", throw new RuntimeException(String.format("Can't find a ConnectionDescriptor for client %s in cache %s",
clientId, connectionDescriptors)); clientId, connectionDescriptors));
} }
connectionDescriptors.sendMessage(pubAckMessage, messageID, clientId); LOG.info("Sending {} message CId=<{}>", MqttMessageType.PUBACK, clientId);
final Optional<ConnectionDescriptor> optDescriptor = connectionDescriptors.lookupDescriptor(clientId);
if (optDescriptor.isPresent()) {
final ConnectionDescriptor descriptor = optDescriptor.get();
descriptor.writeAndFlush(pubAckMessage);
}
} catch (Throwable t) { } catch (Throwable t) {
LOG.error(null, t); LOG.error(null, t);
} }
@@ -16,6 +16,8 @@
package io.moquette.spi.impl; package io.moquette.spi.impl;
import io.moquette.connections.IConnectionsManager;
import io.moquette.server.ConnectionDescriptor;
import io.moquette.server.ConnectionDescriptorStore; import io.moquette.server.ConnectionDescriptorStore;
import io.moquette.server.netty.NettyUtils; import io.moquette.server.netty.NettyUtils;
import io.moquette.spi.ClientSession; import io.moquette.spi.ClientSession;
@@ -29,6 +31,8 @@ import io.netty.handler.codec.mqtt.*;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Optional;
import static io.moquette.spi.impl.DebugUtils.payload2Str; import static io.moquette.spi.impl.DebugUtils.payload2Str;
import static io.moquette.spi.impl.ProtocolProcessor.asStoredMessage; import static io.moquette.spi.impl.ProtocolProcessor.asStoredMessage;
import static io.moquette.spi.impl.Utils.messageId; import static io.moquette.spi.impl.Utils.messageId;
@@ -42,14 +46,14 @@ class Qos2PublishHandler extends QosPublishHandler {
private final ISubscriptionsDirectory subscriptions; private final ISubscriptionsDirectory subscriptions;
private final IMessagesStore m_messagesStore; private final IMessagesStore m_messagesStore;
private final BrokerInterceptor m_interceptor; private final BrokerInterceptor m_interceptor;
private final ConnectionDescriptorStore connectionDescriptors; private final IConnectionsManager connectionDescriptors;
private final MessagesPublisher publisher; private final MessagesPublisher publisher;
private final SessionsRepository sessionsRepository; private final SessionsRepository sessionsRepository;
public Qos2PublishHandler(IAuthorizator authorizator, ISubscriptionsDirectory subscriptions, Qos2PublishHandler(IAuthorizator authorizator, ISubscriptionsDirectory subscriptions,
IMessagesStore messagesStore, BrokerInterceptor interceptor, IMessagesStore messagesStore, BrokerInterceptor interceptor,
ConnectionDescriptorStore connectionDescriptors, IConnectionsManager connectionDescriptors,
MessagesPublisher messagesPublisher, SessionsRepository sessionsRepository) { MessagesPublisher messagesPublisher, SessionsRepository sessionsRepository) {
super(authorizator); super(authorizator);
this.subscriptions = subscriptions; this.subscriptions = subscriptions;
this.m_messagesStore = messagesStore; this.m_messagesStore = messagesStore;
@@ -129,16 +133,34 @@ class Qos2PublishHandler extends QosPublishHandler {
} }
private void sendPubRec(String clientID, int messageID) { private void sendPubRec(String clientID, int messageID) {
LOG.debug("Sending PUBREC message. CId={}, messageId={}", clientID, messageID); LOG.trace("Sending PUBREC message. CId={}, messageId={}", clientID, messageID);
MqttFixedHeader fixedHeader = new MqttFixedHeader(MqttMessageType.PUBREC, false, AT_MOST_ONCE, false, 0); MqttFixedHeader fixedHeader = new MqttFixedHeader(MqttMessageType.PUBREC, false, AT_MOST_ONCE, false, 0);
MqttMessage pubRecMessage = new MqttMessage(fixedHeader, from(messageID)); MqttMessage pubRecMessage = new MqttMessage(fixedHeader, from(messageID));
connectionDescriptors.sendMessage(pubRecMessage, messageID, clientID); final Optional<ConnectionDescriptor> connectionDescriptor = connectionDescriptors.lookupDescriptor(clientID);
if (connectionDescriptor.isPresent()) {
final ConnectionDescriptor descriptor = connectionDescriptor.get();
try {
descriptor.writeAndFlush(pubRecMessage);
} catch (Throwable e) {
LOG.error("Unable to send {} message. CId=<{}>, messageId={}", MqttMessageType.PUBREC, clientID,
messageID, e);
}
}
} }
private void sendPubComp(String clientID, int messageID) { private void sendPubComp(String clientID, int messageID) {
LOG.debug("Sending PUBCOMP message. CId={}, messageId={}", clientID, messageID); LOG.trace("Sending PUBCOMP message. CId={}, messageId={}", clientID, messageID);
MqttFixedHeader fixedHeader = new MqttFixedHeader(MqttMessageType.PUBCOMP, false, AT_MOST_ONCE, false, 0); MqttFixedHeader fixedHeader = new MqttFixedHeader(MqttMessageType.PUBCOMP, false, AT_MOST_ONCE, false, 0);
MqttMessage pubCompMessage = new MqttMessage(fixedHeader, from(messageID)); MqttMessage pubCompMessage = new MqttMessage(fixedHeader, from(messageID));
connectionDescriptors.sendMessage(pubCompMessage, messageID, clientID); final Optional<ConnectionDescriptor> connectionDescriptor = connectionDescriptors.lookupDescriptor(clientID);
if (connectionDescriptor.isPresent()) {
final ConnectionDescriptor descriptor = connectionDescriptor.get();
try {
descriptor.writeAndFlush(pubCompMessage);
} catch (Throwable e) {
LOG.error("Unable to send {} message. CId=<{}>, messageId={}", MqttMessageType.PUBCOMP, clientID,
messageID, e);
}
}
} }
} }