diff --git a/broker/pom.xml b/broker/pom.xml index 29b74dd8..2e7f9983 100644 --- a/broker/pom.xml +++ b/broker/pom.xml @@ -1,5 +1,5 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 ../ @@ -23,37 +23,37 @@ slf4j-api 1.7.5 - + io.netty netty-common ${netty.version} - + io.netty netty-buffer ${netty.version} - + io.netty netty-transport ${netty.version} - + io.netty netty-handler ${netty.version} - + io.netty netty-codec ${netty.version} - + io.netty netty-codec-http @@ -71,13 +71,13 @@ commons-codec 1.10 - + org.mapdb mapdb - - - + + + 1.0.8 @@ -111,11 +111,11 @@ org.mockito - mockito-core - 1.9.0 + mockito-core + 1.9.0 test - + org.fusesource.mqtt-client mqtt-client @@ -129,7 +129,7 @@ 1.0.2 test - + org.eclipse.jetty.websocket websocket-client @@ -152,7 +152,7 @@ test - + @@ -165,32 +165,32 @@ - - + + maven-jar-plugin - + ${project.build.outputDirectory}/META-INF/MANIFEST.MF - + - test-jar + test-jar - - + + org.apache.felix maven-bundle-plugin bundle-manifest process-classes - + manifest - + diff --git a/broker/src/main/java/io/moquette/BrokerConstants.java b/broker/src/main/java/io/moquette/BrokerConstants.java index acbdd234..61d605ba 100644 --- a/broker/src/main/java/io/moquette/BrokerConstants.java +++ b/broker/src/main/java/io/moquette/BrokerConstants.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette; import java.io.File; @@ -21,7 +22,8 @@ import java.io.File; * Created by andrea on 08/12/15. */ public class BrokerConstants { - public static final String INTERCEPT_HANDLER_PROPERTY_NAME ="intercept.handler"; + + public static final String INTERCEPT_HANDLER_PROPERTY_NAME = "intercept.handler"; public static final String BROKER_INTERCEPTOR_THREAD_POOL_SIZE = "intercept.thread_pool.size"; public static final String PERSISTENT_STORE_PROPERTY_NAME = "persistent_store"; public static final String AUTOSAVE_INTERVAL_PROPERTY_NAME = "autosave_interval"; @@ -29,7 +31,8 @@ public class BrokerConstants { public static final String PORT_PROPERTY_NAME = "port"; public static final String HOST_PROPERTY_NAME = "host"; public static final String DEFAULT_MOQUETTE_STORE_MAP_DB_FILENAME = "moquette_store.mapdb"; - public static final String DEFAULT_PERSISTENT_PATH = System.getProperty("user.dir") + File.separator + DEFAULT_MOQUETTE_STORE_MAP_DB_FILENAME; + public static final String DEFAULT_PERSISTENT_PATH = System.getProperty("user.dir") + File.separator + + DEFAULT_MOQUETTE_STORE_MAP_DB_FILENAME; public static final String WEB_SOCKET_PORT_PROPERTY_NAME = "websocket_port"; public static final String WSS_PORT_PROPERTY_NAME = "secure_websocket_port"; public static final String SSL_PORT_PROPERTY_NAME = "ssl_port"; diff --git a/broker/src/main/java/io/moquette/connections/IConnectionsManager.java b/broker/src/main/java/io/moquette/connections/IConnectionsManager.java index 38d4b5ab..14818d54 100644 --- a/broker/src/main/java/io/moquette/connections/IConnectionsManager.java +++ b/broker/src/main/java/io/moquette/connections/IConnectionsManager.java @@ -1,58 +1,60 @@ + package io.moquette.connections; import java.util.Collection; /** - * This interface will be used by an external codebase to retrieve and close - * physical connections. - * + * This interface will be used by an external codebase to retrieve and close physical connections. + * * @author lbarrios * */ public interface IConnectionsManager { - /** - * Returns the number of physical connections - * - * @return - */ - public int getActiveConnectionsNo(); - /** - * Determines wether a MQTT client is connected to the broker. - * - * @param clientID - * @return - */ - public boolean isConnected(String clientID); + /** + * Returns the number of physical connections + * + * @return + */ + public int getActiveConnectionsNo(); - /** - * Returns the identifiers of the MQTT clients that are connected to the - * broker. - * - * @return - */ - public Collection getConnectedClientIds(); + /** + * Determines wether a MQTT client is connected to the broker. + * + * @param clientID + * @return + */ + public boolean isConnected(String clientID); - /** - * Closes a physical connection. - * - * @param clientID - * @param closeImmediately - * If false, the connection will be flushed before it is closed. - * @return - */ - public boolean closeConnection(String clientID, boolean closeImmediately); - - /** - * Returns the state of the session of a given client. - * @param clientID - * @return - */ - public MqttSession getSessionStatus(String clientID); - - /** - * Returns the state of all the sessions - * @return - */ - public Collection getSessions(); + /** + * Returns the identifiers of the MQTT clients that are connected to the broker. + * + * @return + */ + public Collection getConnectedClientIds(); + + /** + * Closes a physical connection. + * + * @param clientID + * @param closeImmediately + * If false, the connection will be flushed before it is closed. + * @return + */ + public boolean closeConnection(String clientID, boolean closeImmediately); + + /** + * Returns the state of the session of a given client. + * + * @param clientID + * @return + */ + public MqttSession getSessionStatus(String clientID); + + /** + * Returns the state of all the sessions + * + * @return + */ + public Collection getSessions(); } diff --git a/broker/src/main/java/io/moquette/connections/MqttConnectionMetrics.java b/broker/src/main/java/io/moquette/connections/MqttConnectionMetrics.java index 5ec7c267..f3daf7c0 100644 --- a/broker/src/main/java/io/moquette/connections/MqttConnectionMetrics.java +++ b/broker/src/main/java/io/moquette/connections/MqttConnectionMetrics.java @@ -1,12 +1,14 @@ + package io.moquette.connections; /** * A class that represents the metrics of a given MQTT connection. - * + * * @author lbarrios * */ public class MqttConnectionMetrics { + private long readKb; private long writtenKb; private long readMessages; diff --git a/broker/src/main/java/io/moquette/connections/MqttSession.java b/broker/src/main/java/io/moquette/connections/MqttSession.java index 6045ebcf..5eee1c67 100644 --- a/broker/src/main/java/io/moquette/connections/MqttSession.java +++ b/broker/src/main/java/io/moquette/connections/MqttSession.java @@ -1,56 +1,56 @@ + package io.moquette.connections; import java.util.Collection; /** - * A class that represents the overall connection status of a MQTT session. Its - * instances will be used by an external codebase when the broker is configured - * in embedded mode. - * + * A class that represents the overall connection status of a MQTT session. Its instances will be + * used by an external codebase when the broker is configured in embedded mode. + * * @author lbarrios * */ public class MqttSession { - private boolean connectionEstablished; - private boolean cleanSession; - private int inflightMessages; - private int pendingPublishMessagesNo; - private int secondPhaseAckPendingMessages; - private Collection activeSubscriptions; - private MqttConnectionMetrics connectionMetrics; + private boolean connectionEstablished; + private boolean cleanSession; + private int inflightMessages; + private int pendingPublishMessagesNo; + private int secondPhaseAckPendingMessages; + private Collection activeSubscriptions; + private MqttConnectionMetrics connectionMetrics; - public boolean isConnectionEstablished() { - return connectionEstablished; - } + public boolean isConnectionEstablished() { + return connectionEstablished; + } - public void setConnectionEstablished(boolean connectionEstablished) { - this.connectionEstablished = connectionEstablished; - } + public void setConnectionEstablished(boolean connectionEstablished) { + this.connectionEstablished = connectionEstablished; + } - public boolean isCleanSession() { - return cleanSession; - } + public boolean isCleanSession() { + return cleanSession; + } - public void setCleanSession(boolean cleanSession) { - this.cleanSession = cleanSession; - } - - public int getPendingPublishMessagesNo() { + public void setCleanSession(boolean cleanSession) { + this.cleanSession = cleanSession; + } + + public int getPendingPublishMessagesNo() { return pendingPublishMessagesNo; } - - public void setPendingPublishMessagesNo(int pendingPublishMessagesNo) { + + public void setPendingPublishMessagesNo(int pendingPublishMessagesNo) { this.pendingPublishMessagesNo = pendingPublishMessagesNo; } - public int getInflightMessages() { - return inflightMessages; - } + public int getInflightMessages() { + return inflightMessages; + } - public void setInflightMessages(int inflightMessages) { - this.inflightMessages = inflightMessages; - } + public void setInflightMessages(int inflightMessages) { + this.inflightMessages = inflightMessages; + } public int getSecondPhaseAckPendingMessages() { return secondPhaseAckPendingMessages; diff --git a/broker/src/main/java/io/moquette/connections/MqttSubscription.java b/broker/src/main/java/io/moquette/connections/MqttSubscription.java index 1e47afa8..ac2790e2 100644 --- a/broker/src/main/java/io/moquette/connections/MqttSubscription.java +++ b/broker/src/main/java/io/moquette/connections/MqttSubscription.java @@ -1,12 +1,14 @@ + package io.moquette.connections; /** - * A class that represents a MQTT subscription. - * + * A class that represents a MQTT subscription. + * * @author lbarrios * */ public class MqttSubscription { + private final String requestedQos; private final String clientId; private final String topicFilter; diff --git a/broker/src/main/java/io/moquette/interception/AbstractInterceptHandler.java b/broker/src/main/java/io/moquette/interception/AbstractInterceptHandler.java index 2f8a9a63..6c99ef51 100644 --- a/broker/src/main/java/io/moquette/interception/AbstractInterceptHandler.java +++ b/broker/src/main/java/io/moquette/interception/AbstractInterceptHandler.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.interception; import io.moquette.interception.messages.InterceptAcknowledgedMessage; @@ -29,30 +30,37 @@ import io.moquette.interception.messages.InterceptUnsubscribeMessage; * Created by andrea on 08/12/15. */ public abstract class AbstractInterceptHandler implements InterceptHandler { - - @Override - public Class[] getInterceptedMessageTypes() { - return InterceptHandler.ALL_MESSAGE_TYPES; - } - - @Override - public void onConnect(InterceptConnectMessage msg) {} @Override - public void onDisconnect(InterceptDisconnectMessage msg) {} + public Class[] getInterceptedMessageTypes() { + return InterceptHandler.ALL_MESSAGE_TYPES; + } @Override - public void onConnectionLost(InterceptConnectionLostMessage msg) {} + public void onConnect(InterceptConnectMessage msg) { + } @Override - public void onPublish(InterceptPublishMessage msg) {} + public void onDisconnect(InterceptDisconnectMessage msg) { + } @Override - public void onSubscribe(InterceptSubscribeMessage msg) {} + public void onConnectionLost(InterceptConnectionLostMessage msg) { + } @Override - public void onUnsubscribe(InterceptUnsubscribeMessage msg) {} - + public void onPublish(InterceptPublishMessage msg) { + } + @Override - public void onMessageAcknowledged(InterceptAcknowledgedMessage msg) {} + public void onSubscribe(InterceptSubscribeMessage msg) { + } + + @Override + public void onUnsubscribe(InterceptUnsubscribeMessage msg) { + } + + @Override + public void onMessageAcknowledged(InterceptAcknowledgedMessage msg) { + } } diff --git a/broker/src/main/java/io/moquette/interception/HazelcastInterceptHandler.java b/broker/src/main/java/io/moquette/interception/HazelcastInterceptHandler.java index 089da44e..5f5bff9f 100644 --- a/broker/src/main/java/io/moquette/interception/HazelcastInterceptHandler.java +++ b/broker/src/main/java/io/moquette/interception/HazelcastInterceptHandler.java @@ -1,3 +1,4 @@ + package io.moquette.interception; import com.hazelcast.core.HazelcastInstance; @@ -7,7 +8,6 @@ import io.moquette.server.Server; import io.netty.buffer.ByteBuf; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import static io.moquette.spi.impl.Utils.readBytesAndRewind; /** @@ -18,18 +18,18 @@ public class HazelcastInterceptHandler extends AbstractInterceptHandler { private static final Logger LOG = LoggerFactory.getLogger(HazelcastInterceptHandler.class); private final HazelcastInstance hz; - public HazelcastInterceptHandler(Server server){ + public HazelcastInterceptHandler(Server server) { this.hz = server.getHazelcastInstance(); } - + @Override public String getID() { - return HazelcastInterceptHandler.class.getName() + "@" + hz.getName(); + return HazelcastInterceptHandler.class.getName() + "@" + hz.getName(); } @Override public void onPublish(InterceptPublishMessage msg) { - //TODO ugly, too much array copy + // TODO ugly, too much array copy ByteBuf payload = msg.getPayload(); byte[] payloadContent = readBytesAndRewind(payload); diff --git a/broker/src/main/java/io/moquette/interception/HazelcastMsg.java b/broker/src/main/java/io/moquette/interception/HazelcastMsg.java index b5d807bb..044d9b81 100644 --- a/broker/src/main/java/io/moquette/interception/HazelcastMsg.java +++ b/broker/src/main/java/io/moquette/interception/HazelcastMsg.java @@ -1,9 +1,8 @@ + package io.moquette.interception; import io.moquette.interception.messages.InterceptPublishMessage; - import java.io.Serializable; - import static io.moquette.spi.impl.Utils.readBytesAndRewind; /** diff --git a/broker/src/main/java/io/moquette/interception/InterceptHandler.java b/broker/src/main/java/io/moquette/interception/InterceptHandler.java index f4bce44c..064b74e4 100644 --- a/broker/src/main/java/io/moquette/interception/InterceptHandler.java +++ b/broker/src/main/java/io/moquette/interception/InterceptHandler.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.interception; import io.moquette.interception.messages.*; @@ -24,32 +25,33 @@ import io.netty.handler.codec.mqtt.MqttMessage; *

* The events can act only as observers. *

- * Almost every method receives a subclass of {@link MqttMessage}, except - * onDisconnect that receives the client id string and - * onSubscribe and onUnsubscribe that receive a - * {@link Subscription} object. + * Almost every method receives a subclass of {@link MqttMessage}, except onDisconnect + * that receives the client id string and onSubscribe and onUnsubscribe + * that receive a {@link Subscription} object. * * @author Wagner Macedo */ public interface InterceptHandler { - - public static final Class ALL_MESSAGE_TYPES[] = { InterceptConnectMessage.class, - InterceptDisconnectMessage.class, InterceptConnectionLostMessage.class, InterceptPublishMessage.class, - InterceptSubscribeMessage.class, InterceptUnsubscribeMessage.class, InterceptAcknowledgedMessage.class }; - - /** - * Returns the identifier of this intercept handler. - * @return - */ - String getID(); - - /** - * Returns the InterceptMessage subtypes that this handler can process. If the result is null or equal to ALL_MESSAGE_TYPES, - * all the message types will be processed. - * @return - */ - Class[] getInterceptedMessageTypes(); - + + Class[] ALL_MESSAGE_TYPES = {InterceptConnectMessage.class, InterceptDisconnectMessage.class, + InterceptConnectionLostMessage.class, InterceptPublishMessage.class, InterceptSubscribeMessage.class, + InterceptUnsubscribeMessage.class, InterceptAcknowledgedMessage.class}; + + /** + * Returns the identifier of this intercept handler. + * + * @return + */ + String getID(); + + /** + * Returns the InterceptMessage subtypes that this handler can process. If the result is null or + * equal to ALL_MESSAGE_TYPES, all the message types will be processed. + * + * @return + */ + Class[] getInterceptedMessageTypes(); + void onConnect(InterceptConnectMessage msg); void onDisconnect(InterceptDisconnectMessage msg); @@ -61,6 +63,6 @@ public interface InterceptHandler { void onSubscribe(InterceptSubscribeMessage msg); void onUnsubscribe(InterceptUnsubscribeMessage msg); - + void onMessageAcknowledged(InterceptAcknowledgedMessage msg); } diff --git a/broker/src/main/java/io/moquette/interception/Interceptor.java b/broker/src/main/java/io/moquette/interception/Interceptor.java index 585024a8..b41dc4b8 100644 --- a/broker/src/main/java/io/moquette/interception/Interceptor.java +++ b/broker/src/main/java/io/moquette/interception/Interceptor.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.interception; import io.moquette.interception.messages.InterceptAcknowledgedMessage; @@ -23,12 +24,10 @@ import io.netty.handler.codec.mqtt.MqttPublishMessage; /** * This interface is to be used internally by the broker components. *

- * An interface is used instead of a class to allow more flexibility in changing - * an implementation. + * An interface is used instead of a class to allow more flexibility in changing an implementation. *

- * Interceptor implementations forward notifications to a InterceptHandler, - * that is normally a field. So, the implementations should act as a proxy to a custom - * intercept handler. + * Interceptor implementations forward notifications to a InterceptHandler, that is + * normally a field. So, the implementations should act as a proxy to a custom intercept handler. * * @see InterceptHandler * @author Wagner Macedo diff --git a/broker/src/main/java/io/moquette/interception/messages/InterceptAbstractMessage.java b/broker/src/main/java/io/moquette/interception/messages/InterceptAbstractMessage.java index 741679e7..26d62fbb 100644 --- a/broker/src/main/java/io/moquette/interception/messages/InterceptAbstractMessage.java +++ b/broker/src/main/java/io/moquette/interception/messages/InterceptAbstractMessage.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.interception.messages; import io.netty.handler.codec.mqtt.MqttMessage; @@ -22,6 +23,7 @@ import io.netty.handler.codec.mqtt.MqttQoS; * @author Wagner Macedo */ public abstract class InterceptAbstractMessage implements InterceptMessage { + private final MqttMessage msg; InterceptAbstractMessage(MqttMessage msg) { diff --git a/broker/src/main/java/io/moquette/interception/messages/InterceptAcknowledgedMessage.java b/broker/src/main/java/io/moquette/interception/messages/InterceptAcknowledgedMessage.java index 6cf31590..f2ce2305 100644 --- a/broker/src/main/java/io/moquette/interception/messages/InterceptAcknowledgedMessage.java +++ b/broker/src/main/java/io/moquette/interception/messages/InterceptAcknowledgedMessage.java @@ -1,27 +1,29 @@ + package io.moquette.interception.messages; import static io.moquette.spi.IMessagesStore.StoredMessage; public class InterceptAcknowledgedMessage implements InterceptMessage { - final private StoredMessage msg; - private final String username; - private final String topic; - - public InterceptAcknowledgedMessage( final StoredMessage msg, final String topic, final String username) { - this.msg = msg; - this.username = username; - this.topic = topic; - } - - public StoredMessage getMsg() { - return msg; - } - public String getUsername() { - return username; - } + final private StoredMessage msg; + private final String username; + private final String topic; - public String getTopic() { - return topic; - } + public InterceptAcknowledgedMessage(final StoredMessage msg, final String topic, final String username) { + this.msg = msg; + this.username = username; + this.topic = topic; + } + + public StoredMessage getMsg() { + return msg; + } + + public String getUsername() { + return username; + } + + public String getTopic() { + return topic; + } } diff --git a/broker/src/main/java/io/moquette/interception/messages/InterceptConnectMessage.java b/broker/src/main/java/io/moquette/interception/messages/InterceptConnectMessage.java index f7be9400..776572cf 100644 --- a/broker/src/main/java/io/moquette/interception/messages/InterceptConnectMessage.java +++ b/broker/src/main/java/io/moquette/interception/messages/InterceptConnectMessage.java @@ -1,3 +1,4 @@ + package io.moquette.interception.messages; import io.netty.handler.codec.mqtt.MqttConnectMessage; @@ -6,6 +7,7 @@ import io.netty.handler.codec.mqtt.MqttConnectMessage; * @author Wagner Macedo */ public class InterceptConnectMessage extends InterceptAbstractMessage { + private final MqttConnectMessage msg; public InterceptConnectMessage(MqttConnectMessage msg) { diff --git a/broker/src/main/java/io/moquette/interception/messages/InterceptConnectionLostMessage.java b/broker/src/main/java/io/moquette/interception/messages/InterceptConnectionLostMessage.java index 1e191ffb..133fa1a8 100644 --- a/broker/src/main/java/io/moquette/interception/messages/InterceptConnectionLostMessage.java +++ b/broker/src/main/java/io/moquette/interception/messages/InterceptConnectionLostMessage.java @@ -1,9 +1,11 @@ + package io.moquette.interception.messages; /** * @author Wagner Macedo */ public class InterceptConnectionLostMessage implements InterceptMessage { + private final String clientID; private final String username; @@ -16,7 +18,7 @@ public class InterceptConnectionLostMessage implements InterceptMessage { return clientID; } - public String getUsername() { - return username; - } + public String getUsername() { + return username; + } } diff --git a/broker/src/main/java/io/moquette/interception/messages/InterceptDisconnectMessage.java b/broker/src/main/java/io/moquette/interception/messages/InterceptDisconnectMessage.java index 0762f10b..d7067c90 100644 --- a/broker/src/main/java/io/moquette/interception/messages/InterceptDisconnectMessage.java +++ b/broker/src/main/java/io/moquette/interception/messages/InterceptDisconnectMessage.java @@ -1,9 +1,11 @@ + package io.moquette.interception.messages; /** * @author Wagner Macedo */ public class InterceptDisconnectMessage implements InterceptMessage { + private final String clientID; private final String username; @@ -16,7 +18,7 @@ public class InterceptDisconnectMessage implements InterceptMessage { return clientID; } - public String getUsername() { - return username; - } + public String getUsername() { + return username; + } } diff --git a/broker/src/main/java/io/moquette/interception/messages/InterceptMessage.java b/broker/src/main/java/io/moquette/interception/messages/InterceptMessage.java index 67539100..b4317409 100644 --- a/broker/src/main/java/io/moquette/interception/messages/InterceptMessage.java +++ b/broker/src/main/java/io/moquette/interception/messages/InterceptMessage.java @@ -1,7 +1,9 @@ + package io.moquette.interception.messages; /** * An interface that sets the root of the interceptor messages type hierarchy. + * * @author lbarrios * */ diff --git a/broker/src/main/java/io/moquette/interception/messages/InterceptPublishMessage.java b/broker/src/main/java/io/moquette/interception/messages/InterceptPublishMessage.java index cbf7b606..1235ab97 100644 --- a/broker/src/main/java/io/moquette/interception/messages/InterceptPublishMessage.java +++ b/broker/src/main/java/io/moquette/interception/messages/InterceptPublishMessage.java @@ -1,3 +1,4 @@ + package io.moquette.interception.messages; import io.netty.buffer.ByteBuf; @@ -7,10 +8,11 @@ import io.netty.handler.codec.mqtt.MqttPublishMessage; * @author Wagner Macedo */ public class InterceptPublishMessage extends InterceptAbstractMessage { + private final MqttPublishMessage msg; private final String clientID; private final String username; - + public InterceptPublishMessage(MqttPublishMessage msg, String clientID, String username) { super(msg); this.msg = msg; @@ -30,7 +32,7 @@ public class InterceptPublishMessage extends InterceptAbstractMessage { return clientID; } - public String getUsername() { - return username; - } + public String getUsername() { + return username; + } } diff --git a/broker/src/main/java/io/moquette/interception/messages/InterceptSubscribeMessage.java b/broker/src/main/java/io/moquette/interception/messages/InterceptSubscribeMessage.java index f2f08d67..b84e3176 100644 --- a/broker/src/main/java/io/moquette/interception/messages/InterceptSubscribeMessage.java +++ b/broker/src/main/java/io/moquette/interception/messages/InterceptSubscribeMessage.java @@ -1,3 +1,4 @@ + package io.moquette.interception.messages; import io.moquette.spi.impl.subscriptions.Subscription; @@ -7,6 +8,7 @@ import io.netty.handler.codec.mqtt.MqttQoS; * @author Wagner Macedo */ public class InterceptSubscribeMessage implements InterceptMessage { + private final Subscription subscription; private final String username; @@ -27,7 +29,7 @@ public class InterceptSubscribeMessage implements InterceptMessage { return subscription.getTopicFilter(); } - public String getUsername() { - return username; - } + public String getUsername() { + return username; + } } diff --git a/broker/src/main/java/io/moquette/interception/messages/InterceptUnsubscribeMessage.java b/broker/src/main/java/io/moquette/interception/messages/InterceptUnsubscribeMessage.java index e8b23707..7968fdb4 100644 --- a/broker/src/main/java/io/moquette/interception/messages/InterceptUnsubscribeMessage.java +++ b/broker/src/main/java/io/moquette/interception/messages/InterceptUnsubscribeMessage.java @@ -1,9 +1,11 @@ + package io.moquette.interception.messages; /** * @author Wagner Macedo */ public class InterceptUnsubscribeMessage implements InterceptMessage { + private final String topicFilter; private final String clientID; private final String username; @@ -22,7 +24,7 @@ public class InterceptUnsubscribeMessage implements InterceptMessage { return clientID; } - public String getUsername() { - return username; - } + public String getUsername() { + return username; + } } diff --git a/broker/src/main/java/io/moquette/logging/LoggingUtils.java b/broker/src/main/java/io/moquette/logging/LoggingUtils.java index d2b7cd21..1de7d55e 100644 --- a/broker/src/main/java/io/moquette/logging/LoggingUtils.java +++ b/broker/src/main/java/io/moquette/logging/LoggingUtils.java @@ -1,16 +1,17 @@ + package io.moquette.logging; import java.util.ArrayList; import java.util.Collection; - import io.moquette.interception.InterceptHandler; public class LoggingUtils { - public static Collection getInterceptorIds(Collection handlers) { - Collection result = new ArrayList<>(handlers.size()); - for (T handler : handlers) { - result.add(handler.getID()); - } - return result; - } + + public static Collection getInterceptorIds(Collection handlers) { + Collection result = new ArrayList<>(handlers.size()); + for (T handler : handlers) { + result.add(handler.getID()); + } + return result; + } } diff --git a/broker/src/main/java/io/moquette/server/ConnectionDescriptor.java b/broker/src/main/java/io/moquette/server/ConnectionDescriptor.java index ddad36e0..9ea41bcf 100644 --- a/broker/src/main/java/io/moquette/server/ConnectionDescriptor.java +++ b/broker/src/main/java/io/moquette/server/ConnectionDescriptor.java @@ -13,15 +13,14 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server; import java.util.NoSuchElementException; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import io.moquette.server.netty.AutoFlushHandler; import io.moquette.server.netty.NettyUtils; import io.moquette.server.netty.metrics.BytesMetrics; @@ -30,10 +29,9 @@ import io.moquette.server.netty.metrics.MessageMetrics; import io.moquette.server.netty.metrics.MessageMetricsHandler; import io.netty.channel.Channel; - /** - * Value object to maintain the information of single connection, like ClientID, Channel, - * and clean session flag. + * Value object to maintain the information of single connection, like ClientID, Channel, and clean + * session flag. * * * @author andrea @@ -43,10 +41,16 @@ public class ConnectionDescriptor { private static final Logger LOG = LoggerFactory.getLogger(ConnectionDescriptor.class); public enum ConnectionState { - //Connection states - DISCONNECTED, SENDACK, SESSION_CREATED, MESSAGES_REPUBLISHED, ESTABLISHED, - //Disconnection states - SUBSCRIPTIONS_REMOVED, MESSAGES_DROPPED, INTERCEPTORS_NOTIFIED; + // Connection states + DISCONNECTED, + SENDACK, + SESSION_CREATED, + MESSAGES_REPUBLISHED, + ESTABLISHED, + // Disconnection states + SUBSCRIPTIONS_REMOVED, + MESSAGES_DROPPED, + INTERCEPTORS_NOTIFIED; } public final String clientID; @@ -59,78 +63,88 @@ public class ConnectionDescriptor { this.channel = session; this.cleanSession = cleanSession; } - + public void writeAndFlush(Object payload) { - this.channel.writeAndFlush(payload); + this.channel.writeAndFlush(payload); } - + public void setupAutoFlusher(int flushIntervalMs) { try { - this.channel.pipeline().addAfter("idleEventHandler", "autoFlusher", new AutoFlushHandler(flushIntervalMs, TimeUnit.MILLISECONDS)); + 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)); + // the idleEventHandler is not present on the pipeline + this.channel.pipeline() + .addFirst("autoFlusher", new AutoFlushHandler(flushIntervalMs, TimeUnit.MILLISECONDS)); } } - + public boolean doesNotUseChannel(Channel channel) { - return !(this.channel.equals(channel)); + return !(this.channel.equals(channel)); } - - public boolean close() { - LOG.info("Closing connection descriptor. MqttClientId = {}.", clientID); - final boolean success = assignState(ConnectionState.INTERCEPTORS_NOTIFIED, ConnectionState.DISCONNECTED); - if (!success) { - return false; - } - this.channel.close(); - return true; - } - + + public boolean close() { + LOG.info("Closing connection descriptor. MqttClientId = {}.", clientID); + final boolean success = assignState(ConnectionState.INTERCEPTORS_NOTIFIED, ConnectionState.DISCONNECTED); + if (!success) { + return false; + } + this.channel.close(); + return true; + } + public String getUsername() { - return NettyUtils.userName(this.channel); + return NettyUtils.userName(this.channel); } public void abort() { - LOG.info("Closing connection descriptor. MqttClientId = {}.", clientID); -// try { - //this.channel.disconnect().sync(); - this.channel.close();//.sync(); -// } catch (InterruptedException e) { -// e.printStackTrace(); -// } + LOG.info("Closing connection descriptor. MqttClientId = {}.", clientID); + // try { + // this.channel.disconnect().sync(); + this.channel.close(); // .sync(); + // } catch (InterruptedException e) { + // e.printStackTrace(); + // } } public boolean assignState(ConnectionState expected, ConnectionState newState) { - LOG.debug("Updating state of connection descriptor. MqttClientId = {}, expectedState = {}, newState = {}.", - clientID, expected, newState); - boolean retval = channelState.compareAndSet(expected, newState); - if (!retval) { - LOG.error( - "Unable to update state of connection descriptor. MqttclientId = {}, expectedState = {}, newState = {}.", - clientID, expected, newState); - } - return retval; - } + LOG.debug( + "Updating state of connection descriptor. MqttClientId = {}, expectedState = {}, newState = {}.", + clientID, + expected, + newState); + boolean retval = channelState.compareAndSet(expected, newState); + if (!retval) { + LOG.error( + "Unable to update state of connection descriptor." + + " MqttclientId = {}, expectedState = {}, newState = {}.", + clientID, + expected, + newState); + } + return retval; + } @Override public String toString() { - return "ConnectionDescriptor{" + "clientID=" + clientID + - ", cleanSession=" + cleanSession + - ", state=" + channelState.get() + - '}'; + return "ConnectionDescriptor{" + "clientID=" + clientID + ", cleanSession=" + cleanSession + ", state=" + + channelState.get() + '}'; } @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; ConnectionDescriptor that = (ConnectionDescriptor) o; - if (clientID != null ? !clientID.equals(that.clientID) : that.clientID != null) return false; + if (clientID != null ? !clientID.equals(that.clientID) : that.clientID != null) + return false; return !(channel != null ? !channel.equals(that.channel) : that.channel != null); - } public BytesMetrics getBytesMetrics() { diff --git a/broker/src/main/java/io/moquette/server/ConnectionDescriptorStore.java b/broker/src/main/java/io/moquette/server/ConnectionDescriptorStore.java index 11463e54..8475bb4c 100644 --- a/broker/src/main/java/io/moquette/server/ConnectionDescriptorStore.java +++ b/broker/src/main/java/io/moquette/server/ConnectionDescriptorStore.java @@ -1,3 +1,4 @@ + package io.moquette.server; import io.moquette.connections.IConnectionsManager; @@ -13,7 +14,6 @@ import io.netty.handler.codec.mqtt.MqttMessage; import io.netty.handler.codec.mqtt.MqttMessageType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.util.ArrayList; import java.util.Collection; import java.util.concurrent.ConcurrentHashMap; @@ -21,64 +21,69 @@ import java.util.concurrent.ConcurrentMap; 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 connectionDescriptors; - private final ISessionsStore sessionsStore; + private final ConcurrentMap connectionDescriptors; + private final ISessionsStore sessionsStore; - public ConnectionDescriptorStore(ISessionsStore sessionsStore) { - this.connectionDescriptors = new ConcurrentHashMap<>(); - this.sessionsStore = sessionsStore; - } + public ConnectionDescriptorStore(ISessionsStore sessionsStore) { + this.connectionDescriptors = new ConcurrentHashMap<>(); + this.sessionsStore = sessionsStore; + } - public boolean sendMessage(MqttMessage message, Integer messageID, String clientID) { + public boolean sendMessage(MqttMessage message, Integer messageID, String clientID) { final MqttMessageType messageType = message.fixedHeader().messageType(); - try { - if (messageID != null) { - LOG.info("Sending {} message CId=<{}>, messageId={}", messageType, clientID, messageID); - } else { - LOG.debug("Sending {} message CId=<{}>", messageType, clientID); - } + try { + if (messageID != null) { + 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. The {} message could not be sent. CId=<{}>, messageId={}", - messageType, clientID, messageID); - } else { - LOG.error("Client has just disconnected. The {} 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) { + ConnectionDescriptor descriptor = connectionDescriptors.get(clientID); + if (descriptor == null) { + if (messageID != null) { + LOG.error( + "Client has just disconnected. The {} message could not be sent. CId=<{}>, messageId={}", + messageType, + clientID, + messageID); + } else { + LOG.error( + "Client has just disconnected. The {} 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) { + if (messageID != null) { errorMsg += ", messageId=" + messageID; - } + } LOG.error(errorMsg, e); - return false; - } - } + return false; + } + } - public ConnectionDescriptor addConnection(ConnectionDescriptor descriptor) { - return connectionDescriptors.putIfAbsent(descriptor.clientID, descriptor); - } + public ConnectionDescriptor addConnection(ConnectionDescriptor descriptor) { + return connectionDescriptors.putIfAbsent(descriptor.clientID, descriptor); + } - public boolean removeConnection(ConnectionDescriptor descriptor) { - return connectionDescriptors.remove(descriptor.clientID, descriptor); - } + public boolean removeConnection(ConnectionDescriptor descriptor) { + return connectionDescriptors.remove(descriptor.clientID, descriptor); + } + + public ConnectionDescriptor getConnection(String clientID) { + return connectionDescriptors.get(clientID); + } - public ConnectionDescriptor getConnection(String clientID) { - return connectionDescriptors.get(clientID); - } - @Override public boolean isConnected(String clientID) { return connectionDescriptors.containsKey(clientID); @@ -99,8 +104,10 @@ public class ConnectionDescriptorStore implements IConnectionsManager { ConnectionDescriptor descriptor = connectionDescriptors.get(clientID); if (descriptor == null) { LOG.error( - "The connection descriptor doesn't exist. The MQTT connection cannot be closed. CId=<{}>, closeImmediately = {}.", - clientID, closeImmediately); + "The connection descriptor doesn't exist. " + + "The MQTT connection cannot be closed. CId=<{}>, closeImmediately = {}.", + clientID, + closeImmediately); return false; } if (closeImmediately) { @@ -125,7 +132,7 @@ public class ConnectionDescriptorStore implements IConnectionsManager { @Override public Collection getSessions() { LOG.info("Retrieving status of all sessions."); - Collection result = new ArrayList(); + Collection result = new ArrayList<>(); for (ClientSession session : sessionsStore.getAllSessions()) { result.add(buildMqttSession(session)); } @@ -136,8 +143,12 @@ public class ConnectionDescriptorStore implements IConnectionsManager { MqttSession result = new MqttSession(); Collection mqttSubscriptions = new ArrayList<>(); for (Subscription subscription : session.getSubscriptions()) { - mqttSubscriptions.add(new MqttSubscription(subscription.getRequestedQos().toString(), - subscription.getClientId(), subscription.getTopicFilter(), subscription.isActive())); + mqttSubscriptions.add( + new MqttSubscription( + subscription.getRequestedQos().toString(), + subscription.getClientId(), + subscription.getTopicFilter(), + subscription.isActive())); } result.setActiveSubscriptions(mqttSubscriptions); result.setCleanSession(session.isCleanSession()); @@ -146,8 +157,12 @@ public class ConnectionDescriptorStore implements IConnectionsManager { result.setConnectionEstablished(true); BytesMetrics bytesMetrics = descriptor.getBytesMetrics(); MessageMetrics messageMetrics = descriptor.getMessageMetrics(); - result.setConnectionMetrics(new MqttConnectionMetrics(bytesMetrics.readBytes(), bytesMetrics.wroteBytes(), - messageMetrics.messagesRead(), messageMetrics.messagesWrote())); + result.setConnectionMetrics( + new MqttConnectionMetrics( + bytesMetrics.readBytes(), + bytesMetrics.wroteBytes(), + messageMetrics.messagesRead(), + messageMetrics.messagesWrote())); } else { result.setConnectionEstablished(false); } diff --git a/broker/src/main/java/io/moquette/server/Constants.java b/broker/src/main/java/io/moquette/server/Constants.java index fc95d550..3a77379b 100644 --- a/broker/src/main/java/io/moquette/server/Constants.java +++ b/broker/src/main/java/io/moquette/server/Constants.java @@ -13,14 +13,16 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server; /** * Server constants keeper */ public class Constants { + public static final String ATTR_CLIENTID = "ClientID"; public static final String CLEAN_SESSION = "cleanSession"; public static final String KEEP_ALIVE = "keepAlive"; - public static final int MAX_MESSAGE_QUEUE = 1024; //number of messages + public static final int MAX_MESSAGE_QUEUE = 1024; // number of messages } diff --git a/broker/src/main/java/io/moquette/server/DefaultMoquetteSslContextCreator.java b/broker/src/main/java/io/moquette/server/DefaultMoquetteSslContextCreator.java index 5c14cace..16bec248 100644 --- a/broker/src/main/java/io/moquette/server/DefaultMoquetteSslContextCreator.java +++ b/broker/src/main/java/io/moquette/server/DefaultMoquetteSslContextCreator.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server; import io.moquette.BrokerConstants; @@ -20,20 +21,18 @@ import io.moquette.server.config.IConfig; import io.moquette.spi.security.ISslContextCreator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; - import java.io.*; import java.net.URL; import java.security.*; import java.security.cert.CertificateException; /** - * Moquette server implementation to load SSL certificate from local filesystem path - * configured in config file. + * Moquette server implementation to load SSL certificate from local filesystem path configured in + * config file. * * Created by andrea on 13/12/15. */ @@ -49,34 +48,34 @@ class DefaultMoquetteSslContextCreator implements ISslContextCreator { @Override public SSLContext initSSLContext() { - LOG.info("Checking SSL configuration properties..."); + LOG.info("Checking SSL configuration properties..."); final String jksPath = props.getProperty(BrokerConstants.JKS_PATH_PROPERTY_NAME); LOG.info("Initializing SSL context. KeystorePath = {}.", jksPath); if (jksPath == null || jksPath.isEmpty()) { - //key_store_password or key_manager_password are empty + // key_store_password or key_manager_password are empty LOG.warn("The keystore path is null or empty. The SSL context won't be initialized."); return null; } - //if we have the port also the jks then keyStorePassword and keyManagerPassword - //has to be defined + // if we have the port also the jks then keyStorePassword and keyManagerPassword + // has to be defined final String keyStorePassword = props.getProperty(BrokerConstants.KEY_STORE_PASSWORD_PROPERTY_NAME); final String keyManagerPassword = props.getProperty(BrokerConstants.KEY_MANAGER_PASSWORD_PROPERTY_NAME); if (keyStorePassword == null || keyStorePassword.isEmpty()) { - //key_store_password or key_manager_password are empty + // key_store_password or key_manager_password are empty LOG.warn("The keystore password is null or empty. The SSL context won't be initialized."); return null; } if (keyManagerPassword == null || keyManagerPassword.isEmpty()) { - //key_manager_password or key_manager_password are empty + // key_manager_password or key_manager_password are empty LOG.warn("The key manager password is null or empty. The SSL context won't be initialized."); return null; } - // if client authentification is enabled a trustmanager needs to be - // added to the ServerContext - String sNeedsClientAuth = props.getProperty(BrokerConstants.NEED_CLIENT_AUTH, "false"); - boolean needsClientAuth = Boolean.valueOf(sNeedsClientAuth); + // if client authentification is enabled a trustmanager needs to be + // added to the ServerContext + String sNeedsClientAuth = props.getProperty(BrokerConstants.NEED_CLIENT_AUTH, "false"); + boolean needsClientAuth = Boolean.valueOf(sNeedsClientAuth); try { LOG.info("Loading keystore. KeystorePath = {}.", jksPath); @@ -87,25 +86,30 @@ class DefaultMoquetteSslContextCreator implements ISslContextCreator { LOG.info("Initializing key manager..."); final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(ks, keyManagerPassword.toCharArray()); - TrustManager[] trustManagers = null; - if (needsClientAuth) { - LOG.warn( - "Client authentication is enabled. The keystore will be used as a truststore. KeystorePath = {}.", - jksPath); - // use keystore as truststore, as server needs to trust certificates signed by the server certificates - TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - tmf.init(ks); - trustManagers = tmf.getTrustManagers(); - } - // init sslContext - LOG.info("Initializing SSL context..."); - serverContext.init(kmf.getKeyManagers(), trustManagers, null); - LOG.info("The SSL context has been initialized successfully."); - + TrustManager[] trustManagers = null; + if (needsClientAuth) { + LOG.warn( + "Client authentication is enabled. " + + "The keystore will be used as a truststore. KeystorePath = {}.", + jksPath); + // use keystore as truststore, as server needs to trust certificates signed by the + // server certificates + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(ks); + trustManagers = tmf.getTrustManagers(); + } + // init sslContext + LOG.info("Initializing SSL context..."); + serverContext.init(kmf.getKeyManagers(), trustManagers, null); + LOG.info("The SSL context has been initialized successfully."); + return serverContext; } catch (NoSuchAlgorithmException | UnrecoverableKeyException | CertificateException | KeyStoreException | KeyManagementException | IOException ex) { - LOG.error("Unable to initialize SSL context. Cause = {}, errorMessage = {}.", ex.getCause(), ex.getMessage()); + LOG.error( + "Unable to initialize SSL context. Cause = {}, errorMessage = {}.", + ex.getCause(), + ex.getMessage()); return null; } } diff --git a/broker/src/main/java/io/moquette/server/HazelcastListener.java b/broker/src/main/java/io/moquette/server/HazelcastListener.java index d0b6aa50..03dff1b9 100644 --- a/broker/src/main/java/io/moquette/server/HazelcastListener.java +++ b/broker/src/main/java/io/moquette/server/HazelcastListener.java @@ -1,3 +1,4 @@ + package io.moquette.server; import com.hazelcast.core.Message; @@ -13,11 +14,12 @@ import org.slf4j.LoggerFactory; * Created by mackristof on 28/05/2016. */ public class HazelcastListener implements MessageListener { + private static final Logger LOG = LoggerFactory.getLogger(HazelcastListener.class); private final Server server; - public HazelcastListener(Server server){ + public HazelcastListener(Server server) { this.server = server; } @@ -26,9 +28,12 @@ public class HazelcastListener implements MessageListener { try { if (!msg.getPublishingMember().equals(server.getHazelcastInstance().getCluster().getLocalMember())) { HazelcastMsg hzMsg = msg.getMessageObject(); - LOG.info("{} received from hazelcast for topic {} message: {}", hzMsg.getClientId(), - hzMsg.getTopic(), hzMsg.getPayload()); - //TODO pass forward this information in somehow publishMessage.setLocal(false); + LOG.info( + "{} received from hazelcast for topic {} message: {}", + hzMsg.getClientId(), + hzMsg.getTopic(), + hzMsg.getPayload()); + // TODO pass forward this information in somehow publishMessage.setLocal(false); MqttQoS qos = MqttQoS.valueOf(hzMsg.getQos()); MqttFixedHeader fixedHeader = new MqttFixedHeader(MqttMessageType.PUBLISH, false, qos, false, 0); diff --git a/broker/src/main/java/io/moquette/server/Server.java b/broker/src/main/java/io/moquette/server/Server.java index f123652f..87074b32 100644 --- a/broker/src/main/java/io/moquette/server/Server.java +++ b/broker/src/main/java/io/moquette/server/Server.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server; import com.hazelcast.config.ClasspathXmlConfig; @@ -38,26 +39,25 @@ import io.moquette.spi.security.ISslContextCreator; import io.netty.handler.codec.mqtt.MqttPublishMessage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Collections; import java.util.List; import java.util.Properties; - import static io.moquette.logging.LoggingUtils.getInterceptorIds; /** - * Launch a configured version of the server. + * Launch a configured version of the server. + * * @author andrea */ public class Server { - + private static final Logger LOG = LoggerFactory.getLogger(Server.class); private static final String HZ_INTERCEPT_HANDLER = HazelcastInterceptHandler.class.getCanonicalName(); - + private ServerAcceptor m_acceptor; private volatile boolean m_initialized; @@ -72,22 +72,24 @@ public class Server { final Server server = new Server(); server.startServer(); System.out.println("Server started, version 0.10-SNAPSHOT"); - //Bind a shutdown hook + // Bind a shutdown hook Runtime.getRuntime().addShutdownHook(new Thread() { + @Override public void run() { server.stopServer(); } }); } - + /** - * Starts Moquette bringing the configuration from the file - * located at m_config/moquette.conf - * @throws IOException in case of any IO error. + * Starts Moquette bringing the configuration from the file located at m_config/moquette.conf + * + * @throws IOException + * in case of any IO error. */ public void startServer() throws IOException { - File defaultConfigurationFile = defaultConfigFile(); + File defaultConfigurationFile = defaultConfigFile(); LOG.info("Starting Moquette server. Configuration file path = {}.", defaultConfigurationFile.getAbsolutePath()); IResourceLoader filesystemLoader = new FileResourceLoader(defaultConfigurationFile); final IConfig config = new ResourceLoaderConfig(filesystemLoader); @@ -101,8 +103,11 @@ public class Server { /** * Starts Moquette bringing the configuration from the given file - * @param configFile text file that contains the configuration. - * @throws IOException in case of any IO Error. + * + * @param configFile + * text file that contains the configuration. + * @throws IOException + * in case of any IO Error. */ public void startServer(File configFile) throws IOException { LOG.info("Starting Moquette server. Configuration file path = {}.", configFile.getAbsolutePath()); @@ -110,50 +115,58 @@ public class Server { final IConfig config = new ResourceLoaderConfig(filesystemLoader); startServer(config); } - + /** * Starts the server with the given properties. - * + * * Its suggested to at least have the following properties: *

    - *
  • port
  • - *
  • password_file
  • + *
  • port
  • + *
  • password_file
  • *
* - * @param configProps the properties map to use as configuration. - * @throws IOException in case of any IO Error. + * @param configProps + * the properties map to use as configuration. + * @throws IOException + * in case of any IO Error. */ public void startServer(Properties configProps) throws IOException { - LOG.info("Starting Moquette server using properties object..."); + LOG.info("Starting Moquette server using properties object..."); final IConfig config = new MemoryConfig(configProps); startServer(config); } /** * Starts Moquette bringing the configuration files from the given Config implementation. - * @param config the configuration to use to start the broker. - * @throws IOException in case of any IO Error. + * + * @param config + * the configuration to use to start the broker. + * @throws IOException + * in case of any IO Error. */ public void startServer(IConfig config) throws IOException { - LOG.info("Starting Moquette server using IConfig instance..."); + LOG.info("Starting Moquette server using IConfig instance..."); startServer(config, null); } /** - * Starts Moquette with config provided by an implementation of IConfig class and with the - * set of InterceptHandler. - * @param config the configuration to use to start the broker. - * @param handlers the handlers to install in the broker. - * @throws IOException in case of any IO Error. - * */ + * Starts Moquette with config provided by an implementation of IConfig class and with the set + * of InterceptHandler. + * + * @param config + * the configuration to use to start the broker. + * @param handlers + * the handlers to install in the broker. + * @throws IOException + * in case of any IO Error. + */ public void startServer(IConfig config, List handlers) throws IOException { - LOG.info("Starting moquette server using IConfig instance and intercept handlers..."); + LOG.info("Starting moquette server using IConfig instance and intercept handlers..."); startServer(config, handlers, null, null, null); } - public void startServer(IConfig config, List handlers, - ISslContextCreator sslCtxCreator, IAuthenticator authenticator, - IAuthorizator authorizator) throws IOException { + public void startServer(IConfig config, List handlers, ISslContextCreator sslCtxCreator, + IAuthenticator authenticator, IAuthorizator authorizator) throws IOException { if (handlers == null) { handlers = Collections.emptyList(); } @@ -164,10 +177,13 @@ public class Server { config.setProperty(BrokerConstants.INTERCEPT_HANDLER_PROPERTY_NAME, handlerProp); } configureCluster(config); - LOG.info("Configuring Using persistent store file. Path = {}.", config.getProperty(BrokerConstants.PERSISTENT_STORE_PROPERTY_NAME)); + LOG.info( + "Configuring Using persistent store file. Path = {}.", + config.getProperty(BrokerConstants.PERSISTENT_STORE_PROPERTY_NAME)); m_processorBootstrapper = new ProtocolProcessorBootstrapper(); LOG.info("Initializing MQTT protocol processor..."); - final ProtocolProcessor processor = m_processorBootstrapper.init(config, handlers, authenticator, authorizator, this); + final ProtocolProcessor processor = m_processorBootstrapper + .init(config, handlers, authenticator, authorizator, this); if (sslCtxCreator == null) { LOG.warn("Using default SSL context creator..."); @@ -184,19 +200,19 @@ public class Server { } private void configureCluster(IConfig config) throws FileNotFoundException { - LOG.info("Configuring embedded Hazelcast instance..."); + LOG.info("Configuring embedded Hazelcast instance..."); String interceptHandlerClassname = config.getProperty(BrokerConstants.INTERCEPT_HANDLER_PROPERTY_NAME); if (interceptHandlerClassname == null || !HZ_INTERCEPT_HANDLER.equals(interceptHandlerClassname)) { - LOG.info("There are no Hazelcast intercept handlers. The server won't start a Hazelcast instance."); + LOG.info("There are no Hazelcast intercept handlers. The server won't start a Hazelcast instance."); return; } String hzConfigPath = config.getProperty(BrokerConstants.HAZELCAST_CONFIGURATION); if (hzConfigPath != null) { boolean isHzConfigOnClasspath = this.getClass().getClassLoader().getResource(hzConfigPath) != null; - Config hzconfig = isHzConfigOnClasspath ? - new ClasspathXmlConfig(hzConfigPath) : - new FileSystemXmlConfig(hzConfigPath); - LOG.info("Starting Hazelcast instance. ConfigurationFile = {}.",hzconfig); + Config hzconfig = isHzConfigOnClasspath + ? new ClasspathXmlConfig(hzConfigPath) + : new FileSystemXmlConfig(hzConfigPath); + LOG.info("Starting Hazelcast instance. ConfigurationFile = {}.", hzconfig); hazelcastInstance = Hazelcast.newHazelcastInstance(hzconfig); } else { LOG.info("Starting Hazelcast instance with default configuration."); @@ -206,43 +222,48 @@ public class Server { } private void listenOnHazelCastMsg() { - LOG.info("Subscribing to Hazelcast topic. TopicName = {}.", "moquette"); + LOG.info("Subscribing to Hazelcast topic. TopicName = {}.", "moquette"); HazelcastInstance hz = getHazelcastInstance(); ITopic topic = hz.getTopic("moquette"); topic.addMessageListener(new HazelcastListener(this)); } - public HazelcastInstance getHazelcastInstance(){ + public HazelcastInstance getHazelcastInstance() { return hazelcastInstance; } /** - * Use the broker to publish a message. It's intended for embedding applications. - * It can be used only after the server is correctly started with startServer. + * Use the broker to publish a message. It's intended for embedding applications. It can be used + * only after the server is correctly started with startServer. * - * @param msg the message to forward. - * @param clientId the id of the sending server. - * @throws IllegalStateException if the server is not yet started - * */ + * @param msg + * the message to forward. + * @param clientId + * the id of the sending server. + * @throws IllegalStateException + * if the server is not yet started + */ public void internalPublish(MqttPublishMessage msg, final String clientId) { final int messageID = msg.variableHeader().messageId(); if (!m_initialized) { - LOG.error("The server is not started. The message cannot be published. MqttClientId = {}, messageId = {}", - clientId, messageID); + LOG.error( + "The server is not started. The message cannot be published. MqttClientId = {}, messageId = {}", + clientId, + messageID); throw new IllegalStateException("Can't publish on a server is not yet started"); } LOG.debug("Publishing message. MqttClientId = {}, messageId = {}", clientId, messageID); m_processor.internalPublish(msg, clientId); } - + public void stopServer() { - LOG.info("Unbinding server from the configured ports..."); + LOG.info("Unbinding server from the configured ports..."); m_acceptor.close(); LOG.info("Stopping MQTT protocol processor..."); m_processorBootstrapper.shutdown(); m_initialized = false; if (hazelcastInstance != null) { - LOG.info("Stopping embedded Hazelcast instance..."); + LOG.info("Stopping embedded Hazelcast instance..."); try { hazelcastInstance.shutdown(); } catch (HazelcastInstanceNotActiveException e) { @@ -253,8 +274,8 @@ public class Server { } /** - * SPI method used by Broker embedded applications to get list of subscribers. - * Returns null if the broker is not started. + * SPI method used by Broker embedded applications to get list of subscribers. Returns null if + * the broker is not started. * * @return list of subscriptions. */ @@ -267,14 +288,16 @@ public class Server { /** * SPI method used by Broker embedded applications to add intercept handlers. - * @param interceptHandler the handler to add. - * */ + * + * @param interceptHandler + * the handler to add. + */ public void addInterceptHandler(InterceptHandler interceptHandler) { if (!m_initialized) { - LOG.error("The server is not started. The MQTT message interceptor cannot be added. InterceptorId = {}.", - interceptHandler.getID()); + LOG.error( + "The server is not started. The MQTT message interceptor cannot be added. InterceptorId = {}.", + interceptHandler.getID()); throw new IllegalStateException("Can't register interceptors on a server that is not yet started"); - } LOG.info("Adding MQTT message interceptor. InterceptorId = {}.", interceptHandler.getID()); m_processor.addInterceptHandler(interceptHandler); @@ -282,12 +305,15 @@ public class Server { /** * SPI method used by Broker embedded applications to remove intercept handlers. - * @param interceptHandler the handler to remove. - * */ + * + * @param interceptHandler + * the handler to remove. + */ public void removeInterceptHandler(InterceptHandler interceptHandler) { if (!m_initialized) { - LOG.error("The server is not started. The MQTT message interceptor cannot be removed. InterceptorId = {}.", - interceptHandler.getID()); + LOG.error( + "The server is not started. The MQTT message interceptor cannot be removed. InterceptorId = {}.", + interceptHandler.getID()); throw new IllegalStateException("Can't deregister interceptors from a server that is not yet started"); } LOG.info("Removing MQTT message interceptor. InterceptorId = {}.", interceptHandler.getID()); @@ -296,7 +322,7 @@ public class Server { /** * Returns the connections manager of this broker. - * + * * @return IConnectionsManager the instance used bt the broker. */ public IConnectionsManager getConnectionsManager() { diff --git a/broker/src/main/java/io/moquette/server/ServerAcceptor.java b/broker/src/main/java/io/moquette/server/ServerAcceptor.java index 53c4bf14..b750715a 100644 --- a/broker/src/main/java/io/moquette/server/ServerAcceptor.java +++ b/broker/src/main/java/io/moquette/server/ServerAcceptor.java @@ -13,10 +13,10 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server; import java.io.IOException; - import io.moquette.server.config.IConfig; import io.moquette.spi.impl.ProtocolProcessor; import io.moquette.spi.security.ISslContextCreator; @@ -26,8 +26,8 @@ import io.moquette.spi.security.ISslContextCreator; * @author andrea */ public interface ServerAcceptor { - + void initialize(ProtocolProcessor processor, IConfig props, ISslContextCreator sslCtxCreator) throws IOException; - + void close(); } diff --git a/broker/src/main/java/io/moquette/server/config/ClasspathResourceLoader.java b/broker/src/main/java/io/moquette/server/config/ClasspathResourceLoader.java index e59462c4..29e37bf2 100644 --- a/broker/src/main/java/io/moquette/server/config/ClasspathResourceLoader.java +++ b/broker/src/main/java/io/moquette/server/config/ClasspathResourceLoader.java @@ -1,16 +1,16 @@ + package io.moquette.server.config; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ClasspathResourceLoader implements IResourceLoader { - private static final Logger LOG = LoggerFactory.getLogger(ClasspathResourceLoader.class); - + private static final Logger LOG = LoggerFactory.getLogger(ClasspathResourceLoader.class); + private final String defaultResource; private final ClassLoader classLoader; @@ -34,7 +34,7 @@ public class ClasspathResourceLoader implements IResourceLoader { @Override public Reader loadResource(String relativePath) { - LOG.info("Loading resource. RelativePath = {}.", relativePath); + LOG.info("Loading resource. RelativePath = {}.", relativePath); InputStream is = this.classLoader.getResourceAsStream(relativePath); return is != null ? new InputStreamReader(is) : null; } diff --git a/broker/src/main/java/io/moquette/server/config/ConfigurationParser.java b/broker/src/main/java/io/moquette/server/config/ConfigurationParser.java index bbc3d912..3b95573f 100644 --- a/broker/src/main/java/io/moquette/server/config/ConfigurationParser.java +++ b/broker/src/main/java/io/moquette/server/config/ConfigurationParser.java @@ -13,11 +13,11 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server.config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; @@ -29,18 +29,18 @@ import java.util.Properties; /** * Mosquitto configuration parser. - * - * A line that at the very first has # is a comment - * Each line has key value format, where the separator used it the space. - * + * + * A line that at the very first has # is a comment Each line has key value format, where the + * separator used it the space. + * * @author andrea */ class ConfigurationParser { - + private static final Logger LOG = LoggerFactory.getLogger(ConfigurationParser.class); - + private Properties m_properties = new Properties(); - + /** * Parse the configuration from file. */ @@ -50,30 +50,38 @@ class ConfigurationParser { return; } if (!file.exists()) { - LOG.warn(String.format("parsing not existing file %s, so fallback on default configuration!", file.getAbsolutePath())); + LOG.warn( + String.format( + "parsing not existing file %s, so fallback on default configuration!", + file.getAbsolutePath())); return; } try { FileReader reader = new FileReader(file); parse(reader); } catch (FileNotFoundException fex) { - LOG.warn(String.format("parsing not existing file %s, so fallback on default configuration!", file.getAbsolutePath()), fex); + LOG.warn( + String.format( + "parsing not existing file %s, so fallback on default configuration!", + file.getAbsolutePath()), + fex); return; } } - + /** - * Parse the configuration - * - * @throws ParseException if the format is not compliant. + * Parse the configuration + * + * @throws ParseException + * if the format is not compliant. */ void parse(Reader reader) throws ParseException { if (reader == null) { - //just log and return default properties + // just log and return default properties LOG.warn("parsing NULL reader, so fallback on default configuration!"); return; } - + BufferedReader br = new BufferedReader(reader); String line; try { @@ -81,39 +89,37 @@ class ConfigurationParser { int commentMarker = line.indexOf('#'); if (commentMarker != -1) { if (commentMarker == 0) { - //skip its a comment + // skip its a comment continue; } else { - //it's a malformed comment + // it's a malformed comment throw new ParseException(line, commentMarker); } } else { if (line.isEmpty() || line.matches("^\\s*$")) { - //skip it's a black line + // skip it's a black line continue; } - - //split till the first space + + // split till the first space int delimiterIdx = line.indexOf(' '); String key = line.substring(0, delimiterIdx).trim(); String value = line.substring(delimiterIdx).trim(); - + m_properties.put(key, value); } } } catch (IOException ex) { throw new ParseException("Failed to read", 1); - } - finally { + } finally { try { reader.close(); - } - catch (IOException e) { + } catch (IOException e) { // ignore } } } - + Properties getProperties() { return m_properties; } diff --git a/broker/src/main/java/io/moquette/server/config/FileResourceLoader.java b/broker/src/main/java/io/moquette/server/config/FileResourceLoader.java index e45b103a..563c87e9 100644 --- a/broker/src/main/java/io/moquette/server/config/FileResourceLoader.java +++ b/broker/src/main/java/io/moquette/server/config/FileResourceLoader.java @@ -1,17 +1,17 @@ + package io.moquette.server.config; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.Reader; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class FileResourceLoader implements IResourceLoader { - private static final Logger LOG = LoggerFactory.getLogger(FileResourceLoader.class); - + private static final Logger LOG = LoggerFactory.getLogger(FileResourceLoader.class); + private final File defaultFile; private final String parentPath; @@ -47,15 +47,15 @@ public class FileResourceLoader implements IResourceLoader { } public Reader loadResource(File f) { - LOG.info("Loading file. Path = {}.", f.getAbsolutePath()); + LOG.info("Loading file. Path = {}.", f.getAbsolutePath()); if (f.isDirectory()) { - LOG.error("The given file is a directory. Path = {}.", f.getAbsolutePath()); + LOG.error("The given file is a directory. Path = {}.", f.getAbsolutePath()); throw new ResourceIsDirectoryException("File \"" + f + "\" is a directory!"); } try { return new FileReader(f); } catch (FileNotFoundException e) { - LOG.error("The file does not exist. Path = {}.", f.getAbsolutePath()); + LOG.error("The file does not exist. Path = {}.", f.getAbsolutePath()); return null; } } diff --git a/broker/src/main/java/io/moquette/server/config/IConfig.java b/broker/src/main/java/io/moquette/server/config/IConfig.java index f836f61d..55ebaeca 100644 --- a/broker/src/main/java/io/moquette/server/config/IConfig.java +++ b/broker/src/main/java/io/moquette/server/config/IConfig.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server.config; import io.moquette.BrokerConstants; @@ -23,6 +24,7 @@ import io.moquette.BrokerConstants; * @author andrea */ public abstract class IConfig { + public static final String DEFAULT_CONFIG = "config/moquette.conf"; public abstract void setProperty(String name, String value); @@ -34,9 +36,11 @@ public abstract class IConfig { void assignDefaults() { setProperty(BrokerConstants.PORT_PROPERTY_NAME, Integer.toString(BrokerConstants.PORT)); setProperty(BrokerConstants.HOST_PROPERTY_NAME, BrokerConstants.HOST); - //setProperty(BrokerConstants.WEB_SOCKET_PORT_PROPERTY_NAME, Integer.toString(BrokerConstants.WEBSOCKET_PORT)); + // setProperty(BrokerConstants.WEB_SOCKET_PORT_PROPERTY_NAME, + // Integer.toString(BrokerConstants.WEBSOCKET_PORT)); setProperty(BrokerConstants.PASSWORD_FILE_PROPERTY_NAME, ""); - //setProperty(BrokerConstants.PERSISTENT_STORE_PROPERTY_NAME, BrokerConstants.DEFAULT_PERSISTENT_PATH); + // setProperty(BrokerConstants.PERSISTENT_STORE_PROPERTY_NAME, + // BrokerConstants.DEFAULT_PERSISTENT_PATH); setProperty(BrokerConstants.ALLOW_ANONYMOUS_PROPERTY_NAME, Boolean.TRUE.toString()); setProperty(BrokerConstants.AUTHENTICATOR_CLASS_NAME, ""); setProperty(BrokerConstants.AUTHORIZATOR_CLASS_NAME, ""); diff --git a/broker/src/main/java/io/moquette/server/config/IResourceLoader.java b/broker/src/main/java/io/moquette/server/config/IResourceLoader.java index afcb1917..e18ec28c 100644 --- a/broker/src/main/java/io/moquette/server/config/IResourceLoader.java +++ b/broker/src/main/java/io/moquette/server/config/IResourceLoader.java @@ -1,3 +1,4 @@ + package io.moquette.server.config; import java.io.Reader; diff --git a/broker/src/main/java/io/moquette/server/config/MemoryConfig.java b/broker/src/main/java/io/moquette/server/config/MemoryConfig.java index 4a5e2355..a1c8cdb3 100644 --- a/broker/src/main/java/io/moquette/server/config/MemoryConfig.java +++ b/broker/src/main/java/io/moquette/server/config/MemoryConfig.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server.config; import java.util.Map; @@ -34,16 +35,18 @@ public class MemoryConfig extends IConfig { } } -// private void createDefaults() { -// m_properties.put(BrokerConstants.PORT_PROPERTY_NAME, Integer.toString(BrokerConstants.PORT)); -// m_properties.put(BrokerConstants.HOST_PROPERTY_NAME, BrokerConstants.HOST); -// m_properties.put(BrokerConstants.WEB_SOCKET_PORT_PROPERTY_NAME, Integer.toString(BrokerConstants.WEBSOCKET_PORT)); -// m_properties.put(BrokerConstants.PASSWORD_FILE_PROPERTY_NAME, ""); -// m_properties.put(BrokerConstants.PERSISTENT_STORE_PROPERTY_NAME, BrokerConstants.DEFAULT_PERSISTENT_PATH); -// m_properties.put(BrokerConstants.ALLOW_ANONYMOUS_PROPERTY_NAME, true); -// m_properties.put(BrokerConstants.AUTHENTICATOR_CLASS_NAME, ""); -// m_properties.put(BrokerConstants.AUTHORIZATOR_CLASS_NAME, ""); -// } + // private void createDefaults() { + // m_properties.put(BrokerConstants.PORT_PROPERTY_NAME, Integer.toString(BrokerConstants.PORT)); + // m_properties.put(BrokerConstants.HOST_PROPERTY_NAME, BrokerConstants.HOST); + // m_properties.put(BrokerConstants.WEB_SOCKET_PORT_PROPERTY_NAME, + // Integer.toString(BrokerConstants.WEBSOCKET_PORT)); + // m_properties.put(BrokerConstants.PASSWORD_FILE_PROPERTY_NAME, ""); + // m_properties.put(BrokerConstants.PERSISTENT_STORE_PROPERTY_NAME, + // BrokerConstants.DEFAULT_PERSISTENT_PATH); + // m_properties.put(BrokerConstants.ALLOW_ANONYMOUS_PROPERTY_NAME, true); + // m_properties.put(BrokerConstants.AUTHENTICATOR_CLASS_NAME, ""); + // m_properties.put(BrokerConstants.AUTHORIZATOR_CLASS_NAME, ""); + // } @Override public void setProperty(String name, String value) { diff --git a/broker/src/main/java/io/moquette/server/config/ResourceLoaderConfig.java b/broker/src/main/java/io/moquette/server/config/ResourceLoaderConfig.java index 9315e798..8a824389 100644 --- a/broker/src/main/java/io/moquette/server/config/ResourceLoaderConfig.java +++ b/broker/src/main/java/io/moquette/server/config/ResourceLoaderConfig.java @@ -13,11 +13,11 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server.config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.io.Reader; import java.text.ParseException; import java.util.Properties; @@ -39,38 +39,45 @@ public class ResourceLoaderConfig extends IConfig { public ResourceLoaderConfig(IResourceLoader resourceLoader, String configName) { LOG.info("Loading configuration. ResourceLoader = {}, configName = {}.", resourceLoader.getName(), configName); this.resourceLoader = resourceLoader; - + /* - * If we use a conditional operator, the loadResource() and the - * loadDefaultResource() methods will be always called. This makes the - * log traces confusing. - */ - + * If we use a conditional operator, the loadResource() and the loadDefaultResource() + * methods will be always called. This makes the log traces confusing. + */ + Reader configReader; if (configName != null) { - configReader = resourceLoader.loadResource(configName); + configReader = resourceLoader.loadResource(configName); } else { - configReader = resourceLoader.loadDefaultResource(); + configReader = resourceLoader.loadDefaultResource(); } - + if (configReader == null) { - LOG.error("The resource loader returned no configuration reader. ResourceLoader = {}, configName = {}.", - resourceLoader.getName(), configName); - throw new IllegalArgumentException("Can't locate " + resourceLoader.getName() + " \"" + configName + "\""); + LOG.error( + "The resource loader returned no configuration reader. ResourceLoader = {}, configName = {}.", + resourceLoader.getName(), + configName); + throw new IllegalArgumentException("Can't locate " + resourceLoader.getName() + " \"" + configName + "\""); } - - LOG.info("Parsing configuration properties. ResourceLoader = {}, configName = {}.", resourceLoader.getName(), - configName); + + LOG.info( + "Parsing configuration properties. ResourceLoader = {}, configName = {}.", + resourceLoader.getName(), + configName); ConfigurationParser confParser = new ConfigurationParser(); m_properties = confParser.getProperties(); assignDefaults(); - try { - confParser.parse(configReader); - } catch (ParseException pex) { - LOG.warn( - "Unable to parse configuration properties. Using default configuration. ResourceLoader = {}, configName = {}, cause = {}, errorMessage = {}.", - resourceLoader.getName(), configName, pex.getCause(), pex.getMessage()); - } + try { + confParser.parse(configReader); + } catch (ParseException pex) { + LOG.warn( + "Unable to parse configuration properties. Using default configuration. " + + "ResourceLoader = {}, configName = {}, cause = {}, errorMessage = {}.", + resourceLoader.getName(), + configName, + pex.getCause(), + pex.getMessage()); + } } @Override diff --git a/broker/src/main/java/io/moquette/server/netty/AutoFlushHandler.java b/broker/src/main/java/io/moquette/server/netty/AutoFlushHandler.java index a802de09..92db1c59 100644 --- a/broker/src/main/java/io/moquette/server/netty/AutoFlushHandler.java +++ b/broker/src/main/java/io/moquette/server/netty/AutoFlushHandler.java @@ -13,33 +13,31 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server.netty; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.util.concurrent.EventExecutor; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; /** - * Auto-flush data on channel after a read timeout. - * It's inspired by IdleStateHandler but it's specialized version, just flushing data after - * no read is done on the channel after a period. It's used to avoid aggressively flushing from - * the ProtocolProcessor. + * Auto-flush data on channel after a read timeout. It's inspired by IdleStateHandler but it's + * specialized version, just flushing data after no read is done on the channel after a period. It's + * used to avoid aggressively flushing from the ProtocolProcessor. */ public class AutoFlushHandler extends ChannelDuplexHandler { - private static final Logger LOG = LoggerFactory.getLogger(AutoFlushHandler.class); + private static final Logger LOG = LoggerFactory.getLogger(AutoFlushHandler.class); private static final long MIN_TIMEOUT_NANOS = TimeUnit.MILLISECONDS.toNanos(1); private final long writerIdleTimeNanos; volatile ScheduledFuture writerIdleTimeout; volatile long lastWriteTime; -// private boolean firstWriterIdleEvent = true; + // private boolean firstWriterIdleEvent = true; private volatile int state; // 0 - none, 1 - initialized, 2 - destroyed @@ -57,7 +55,7 @@ public class AutoFlushHandler extends ChannelDuplexHandler { // not be invoked. We have to initialize here instead. initialize(ctx); } else { - // channelActive() event has not been fired yet. this.channelActive() will be invoked + // channelActive() event has not been fired yet. this.channelActive() will be invoked // and initialization will occur there. } } @@ -79,7 +77,7 @@ public class AutoFlushHandler extends ChannelDuplexHandler { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { // This method will be invoked only if this handler was added - // before channelActive() event is fired. If a user adds this handler + // before channelActive() event is fired. If a user adds this handler // after the channelActive() event, initialize() will be called by beforeAdd(). initialize(ctx); super.channelActive(ctx); @@ -91,30 +89,30 @@ public class AutoFlushHandler extends ChannelDuplexHandler { super.channelInactive(ctx); } -// @Override -// public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { -// if (writerrIdleTimeNanos > 0) { -// reading = true; -// firstReaderIdleEvent = true; -// } -// ctx.fireChannelRead(msg); -// } -// -// @Override -// public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { -// if (writerrIdleTimeNanos > 0) { -// lastReadTime = System.nanoTime(); -// reading = false; -// } -// ctx.fireChannelReadComplete(); -// } + // @Override + // public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // if (writerrIdleTimeNanos > 0) { + // reading = true; + // firstReaderIdleEvent = true; + // } + // ctx.fireChannelRead(msg); + // } + // + // @Override + // public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + // if (writerrIdleTimeNanos > 0) { + // lastReadTime = System.nanoTime(); + // reading = false; + // } + // ctx.fireChannelReadComplete(); + // } private void initialize(ChannelHandlerContext ctx) { // Avoid the case where destroy() is called before scheduling timeouts. // See: https://github.com/netty/netty/issues/143 - if (LOG.isDebugEnabled()) { - LOG.debug("Initializing autoflush handler. MqttClientId = {}.", NettyUtils.clientID(ctx.channel())); - } + if (LOG.isDebugEnabled()) { + LOG.debug("Initializing autoflush handler. MqttClientId = {}.", NettyUtils.clientID(ctx.channel())); + } switch (state) { case 1: case 2: @@ -126,9 +124,7 @@ public class AutoFlushHandler extends ChannelDuplexHandler { EventExecutor loop = ctx.executor(); lastWriteTime = System.nanoTime(); - writerIdleTimeout = loop.schedule( - new WriterIdleTimeoutTask(ctx), - writerIdleTimeNanos, TimeUnit.NANOSECONDS); + writerIdleTimeout = loop.schedule(new WriterIdleTimeoutTask(ctx), writerIdleTimeNanos, TimeUnit.NANOSECONDS); } private void destroy() { @@ -143,14 +139,16 @@ public class AutoFlushHandler extends ChannelDuplexHandler { /** * Is called when the write timeout expire. * - * @param ctx the channel context. - * @throws Exception in case of any IO error. + * @param ctx + * the channel context. + * @throws Exception + * in case of any IO error. */ - protected void channelIdle(ChannelHandlerContext ctx/*, IdleStateEvent evt*/) throws Exception { -// ctx.fireUserEventTriggered(evt); - if (LOG.isDebugEnabled()) { - LOG.debug("Flushing idle Netty channel. MqttClientId = {}.", NettyUtils.clientID(ctx.channel())); - } + protected void channelIdle(ChannelHandlerContext ctx/* , IdleStateEvent evt */) throws Exception { + // ctx.fireUserEventTriggered(evt); + if (LOG.isDebugEnabled()) { + LOG.debug("Flushing idle Netty channel. MqttClientId = {}.", NettyUtils.clientID(ctx.channel())); + } ctx.channel().flush(); } @@ -168,22 +166,19 @@ public class AutoFlushHandler extends ChannelDuplexHandler { return; } -// long lastWriteTime = IdleStateHandler.this.lastWriteTime; -// long lastWriteTime = lastWriteTime; + // long lastWriteTime = IdleStateHandler.this.lastWriteTime; + // long lastWriteTime = lastWriteTime; long nextDelay = writerIdleTimeNanos - (System.nanoTime() - lastWriteTime); if (nextDelay <= 0) { // Writer is idle - set a new timeout and notify the callback. - writerIdleTimeout = ctx.executor().schedule( - this, writerIdleTimeNanos, TimeUnit.NANOSECONDS); + writerIdleTimeout = ctx.executor().schedule(this, writerIdleTimeNanos, TimeUnit.NANOSECONDS); try { - /*IdleStateEvent event; - if (firstWriterIdleEvent) { - firstWriterIdleEvent = false; - event = IdleStateEvent.FIRST_WRITER_IDLE_STATE_EVENT; - } else { - event = IdleStateEvent.WRITER_IDLE_STATE_EVENT; - }*/ - channelIdle(ctx/*, event*/); + /* + * IdleStateEvent event; if (firstWriterIdleEvent) { firstWriterIdleEvent = + * false; event = IdleStateEvent.FIRST_WRITER_IDLE_STATE_EVENT; } else { event = + * IdleStateEvent.WRITER_IDLE_STATE_EVENT; } + */ + channelIdle(ctx/* , event */); } catch (Throwable t) { ctx.fireExceptionCaught(t); } diff --git a/broker/src/main/java/io/moquette/server/netty/MessageBuilder.java b/broker/src/main/java/io/moquette/server/netty/MessageBuilder.java index bf1180c3..b7e90b80 100644 --- a/broker/src/main/java/io/moquette/server/netty/MessageBuilder.java +++ b/broker/src/main/java/io/moquette/server/netty/MessageBuilder.java @@ -13,17 +13,18 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server.netty; import io.netty.buffer.Unpooled; import io.netty.handler.codec.mqtt.*; - import java.util.ArrayList; import java.util.List; public class MessageBuilder { public static class PublishBuilder { + private String topic = null; private boolean retained = false; private MqttQoS qos; @@ -138,19 +139,28 @@ public class MessageBuilder { } public MqttConnectMessage build() { - MqttFixedHeader mqttFixedHeader = new MqttFixedHeader(MqttMessageType.CONNECT, false, MqttQoS.AT_MOST_ONCE, false, 0); - MqttConnectVariableHeader mqttConnectVariableHeader = - new MqttConnectVariableHeader( - version.protocolName(), - version.protocolLevel(), - hasUser, - hasPassword, - false, - willQos.value(), - willFlag, - cleanSession, - keepAliveSecs); - MqttConnectPayload mqttConnectPayload = new MqttConnectPayload(clientId, willTopic, willMessage, username, password); + MqttFixedHeader mqttFixedHeader = new MqttFixedHeader( + MqttMessageType.CONNECT, + false, + MqttQoS.AT_MOST_ONCE, + false, + 0); + MqttConnectVariableHeader mqttConnectVariableHeader = new MqttConnectVariableHeader( + version.protocolName(), + version.protocolLevel(), + hasUser, + hasPassword, + false, + willQos.value(), + willFlag, + cleanSession, + keepAliveSecs); + MqttConnectPayload mqttConnectPayload = new MqttConnectPayload( + clientId, + willTopic, + willMessage, + username, + password); return new MqttConnectMessage(mqttFixedHeader, mqttConnectVariableHeader, mqttConnectPayload); } } @@ -171,7 +181,12 @@ public class MessageBuilder { } public MqttSubscribeMessage build() { - MqttFixedHeader mqttFixedHeader = new MqttFixedHeader(MqttMessageType.SUBSCRIBE, false, MqttQoS.AT_LEAST_ONCE, false, 0); + MqttFixedHeader mqttFixedHeader = new MqttFixedHeader( + MqttMessageType.SUBSCRIBE, + false, + MqttQoS.AT_LEAST_ONCE, + false, + 0); MqttMessageIdVariableHeader mqttVariableHeader = MqttMessageIdVariableHeader.from(messageId); MqttSubscribePayload mqttSubscribePayload = new MqttSubscribePayload(subscriptions); return new MqttSubscribeMessage(mqttFixedHeader, mqttVariableHeader, mqttSubscribePayload); @@ -194,8 +209,12 @@ public class MessageBuilder { } public MqttUnsubscribeMessage build() { - MqttFixedHeader mqttFixedHeader = new MqttFixedHeader(MqttMessageType.UNSUBSCRIBE, false, - MqttQoS.AT_LEAST_ONCE, false, 0); + MqttFixedHeader mqttFixedHeader = new MqttFixedHeader( + MqttMessageType.UNSUBSCRIBE, + false, + MqttQoS.AT_LEAST_ONCE, + false, + 0); MqttMessageIdVariableHeader mqttVariableHeader = MqttMessageIdVariableHeader.from(messageId); MqttUnsubscribePayload mqttSubscribePayload = new MqttUnsubscribePayload(topicFilters); return new MqttUnsubscribeMessage(mqttFixedHeader, mqttVariableHeader, mqttSubscribePayload); diff --git a/broker/src/main/java/io/moquette/server/netty/MoquetteIdleTimeoutHandler.java b/broker/src/main/java/io/moquette/server/netty/MoquetteIdleTimeoutHandler.java index 69378b62..3e93a9e7 100644 --- a/broker/src/main/java/io/moquette/server/netty/MoquetteIdleTimeoutHandler.java +++ b/broker/src/main/java/io/moquette/server/netty/MoquetteIdleTimeoutHandler.java @@ -13,11 +13,11 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server.netty; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; @@ -26,24 +26,26 @@ import io.netty.handler.timeout.IdleStateEvent; @Sharable class MoquetteIdleTimeoutHandler extends ChannelDuplexHandler { - - private static final Logger LOG = LoggerFactory.getLogger(MoquetteIdleTimeoutHandler.class); - + + private static final Logger LOG = LoggerFactory.getLogger(MoquetteIdleTimeoutHandler.class); + @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof IdleStateEvent) { IdleState e = ((IdleStateEvent) evt).state(); if (e == IdleState.ALL_IDLE) { - LOG.info("Firing channel inactive event. MqttClientId = {}.", NettyUtils.clientID(ctx.channel())); - //fire a channelInactive to trigger publish of Will + LOG.info("Firing channel inactive event. MqttClientId = {}.", NettyUtils.clientID(ctx.channel())); + // fire a channelInactive to trigger publish of Will ctx.fireChannelInactive(); ctx.close(); } } else { - if (LOG.isDebugEnabled()) { - LOG.debug("Firing Netty event. MqttClientId = {}, eventClass = {}.", NettyUtils.clientID(ctx.channel()), - evt.getClass().getName()); - } + if (LOG.isDebugEnabled()) { + LOG.debug( + "Firing Netty event. MqttClientId = {}, eventClass = {}.", + NettyUtils.clientID(ctx.channel()), + evt.getClass().getName()); + } super.userEventTriggered(ctx, evt); } } diff --git a/broker/src/main/java/io/moquette/server/netty/NettyAcceptor.java b/broker/src/main/java/io/moquette/server/netty/NettyAcceptor.java index 403838c6..9e307019 100644 --- a/broker/src/main/java/io/moquette/server/netty/NettyAcceptor.java +++ b/broker/src/main/java/io/moquette/server/netty/NettyAcceptor.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server.netty; import io.moquette.BrokerConstants; @@ -42,13 +43,11 @@ import io.netty.handler.timeout.IdleStateHandler; import io.netty.util.concurrent.Future; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import java.io.IOException; import java.util.List; import java.util.concurrent.TimeUnit; - import static io.moquette.BrokerConstants.*; /** @@ -56,28 +55,31 @@ import static io.moquette.BrokerConstants.*; * @author andrea */ public class NettyAcceptor implements ServerAcceptor { - + private static final String MQTT_SUBPROTOCOL_CSV_LIST = "mqtt, mqttv3.1, mqttv3.1.1"; static class WebSocketFrameToByteBufDecoder extends MessageToMessageDecoder { @Override - protected void decode(ChannelHandlerContext chc, BinaryWebSocketFrame frame, List out) throws Exception { - //convert the frame to a ByteBuf + protected void decode(ChannelHandlerContext chc, BinaryWebSocketFrame frame, List out) + throws Exception { + // convert the frame to a ByteBuf ByteBuf bb = frame.content(); - //System.out.println("WebSocketFrameToByteBufDecoder decode - " + ByteBufUtil.hexDump(bb)); + // System.out.println("WebSocketFrameToByteBufDecoder decode - " + + // ByteBufUtil.hexDump(bb)); bb.retain(); out.add(bb); } } - + static class ByteBufToWebSocketFrameEncoder extends MessageToMessageEncoder { @Override protected void encode(ChannelHandlerContext chc, ByteBuf bb, List out) throws Exception { - //convert the ByteBuf to a WebSocketFrame + // convert the ByteBuf to a WebSocketFrame BinaryWebSocketFrame result = new BinaryWebSocketFrame(); - //System.out.println("ByteBufToWebSocketFrameEncoder encode - " + ByteBufUtil.hexDump(bb)); + // System.out.println("ByteBufToWebSocketFrameEncoder encode - " + + // ByteBufUtil.hexDump(bb)); result.content().writeBytes(bb); out.add(result); } @@ -89,7 +91,7 @@ public class NettyAcceptor implements ServerAcceptor { } private static final Logger LOG = LoggerFactory.getLogger(NettyAcceptor.class); - + EventLoopGroup m_bossGroup; EventLoopGroup m_workerGroup; BytesMetricsCollector m_bytesMetricsCollector = new BytesMetricsCollector(); @@ -102,20 +104,24 @@ public class NettyAcceptor implements ServerAcceptor { private int nettyChannelTimeoutSeconds; @Override - public void initialize(ProtocolProcessor processor, IConfig props, ISslContextCreator sslCtxCreator) throws IOException { + public void initialize(ProtocolProcessor processor, IConfig props, ISslContextCreator sslCtxCreator) + throws IOException { LOG.info("Initializing Netty acceptor..."); nettySoBacklog = Integer.parseInt(props.getProperty(BrokerConstants.NETTY_SO_BACKLOG_PROPERTY_NAME, "128")); - nettySoReuseaddr = Boolean.parseBoolean(props.getProperty(BrokerConstants.NETTY_SO_REUSEADDR_PROPERTY_NAME, "true")); - nettyTcpNodelay = Boolean.parseBoolean(props.getProperty(BrokerConstants.NETTY_TCP_NODELAY_PROPERTY_NAME, "true")); - nettySoKeepalive = Boolean.parseBoolean(props.getProperty(BrokerConstants.NETTY_SO_KEEPALIVE_PROPERTY_NAME, "true")); + nettySoReuseaddr = Boolean + .parseBoolean(props.getProperty(BrokerConstants.NETTY_SO_REUSEADDR_PROPERTY_NAME, "true")); + nettyTcpNodelay = Boolean + .parseBoolean(props.getProperty(BrokerConstants.NETTY_TCP_NODELAY_PROPERTY_NAME, "true")); + nettySoKeepalive = Boolean + .parseBoolean(props.getProperty(BrokerConstants.NETTY_SO_KEEPALIVE_PROPERTY_NAME, "true")); nettyChannelTimeoutSeconds = Integer .parseInt(props.getProperty(BrokerConstants.NETTY_CHANNEL_TIMEOUT_SECONDS_PROPERTY_NAME, "10")); - + m_bossGroup = new NioEventLoopGroup(); m_workerGroup = new NioEventLoopGroup(); final NettyMQTTHandler handler = new NettyMQTTHandler(processor); - + initializePlainTCPTransport(handler, props); initializeWebSocketTransport(handler, props); String sslTcpPortProp = props.getProperty(BrokerConstants.SSL_PORT_PROPERTY_NAME); @@ -132,11 +138,11 @@ public class NettyAcceptor implements ServerAcceptor { } private void initFactory(String host, int port, String protocol, final PipelineInitializer pipeliner) { - LOG.info("Initializing server. Protocol = {}.", protocol); + LOG.info("Initializing server. Protocol = {}.", protocol); ServerBootstrap b = new ServerBootstrap(); - b.group(m_bossGroup, m_workerGroup) - .channel(NioServerSocketChannel.class) + b.group(m_bossGroup, m_workerGroup).channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer() { + @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); @@ -147,13 +153,11 @@ public class NettyAcceptor implements ServerAcceptor { throw th; } } - }) - .option(ChannelOption.SO_BACKLOG, nettySoBacklog) - .option(ChannelOption.SO_REUSEADDR, nettySoReuseaddr) + }).option(ChannelOption.SO_BACKLOG, nettySoBacklog).option(ChannelOption.SO_REUSEADDR, nettySoReuseaddr) .option(ChannelOption.TCP_NODELAY, nettyTcpNodelay) .childOption(ChannelOption.SO_KEEPALIVE, nettySoKeepalive); try { - LOG.info("Binding server. Protocol = {}, host = {}, port = {}.", host, port); + LOG.info("Binding server. Protocol = {}, host = {}, port = {}.", host, port); // Bind and start to accept incoming connections. ChannelFuture f = b.bind(host, port); LOG.info("The server has been binded. Protocol = {}, host = {}, port = {}", host, port); @@ -162,23 +166,27 @@ public class NettyAcceptor implements ServerAcceptor { LOG.error("An interruptedException was caught while initializing server. Protocol = {}.", protocol, ex); } } - + private void initializePlainTCPTransport(final NettyMQTTHandler handler, IConfig props) throws IOException { - LOG.info("Configuring TCP MQTT transport..."); + LOG.info("Configuring TCP MQTT transport..."); final MoquetteIdleTimeoutHandler timeoutHandler = new MoquetteIdleTimeoutHandler(); String host = props.getProperty(BrokerConstants.HOST_PROPERTY_NAME); String tcpPortProp = props.getProperty(PORT_PROPERTY_NAME, DISABLED_PORT_BIND); if (DISABLED_PORT_BIND.equals(tcpPortProp)) { - LOG.info("The property {} has been setted to {}. TCP MQTT will be disabled.", BrokerConstants.PORT_PROPERTY_NAME, DISABLED_PORT_BIND); + LOG.info( + "The property {} has been setted to {}. TCP MQTT will be disabled.", + BrokerConstants.PORT_PROPERTY_NAME, + DISABLED_PORT_BIND); return; } int port = Integer.parseInt(tcpPortProp); initFactory(host, port, "TCP MQTT", new PipelineInitializer() { + @Override void init(ChannelPipeline pipeline) { pipeline.addFirst("idleStateHandler", new IdleStateHandler(0, 0, nettyChannelTimeoutSeconds)); pipeline.addAfter("idleStateHandler", "idleEventHandler", timeoutHandler); -// pipeline.addLast("logger", new LoggingHandler("Netty", LogLevel.ERROR)); + // pipeline.addLast("logger", new LoggingHandler("Netty", LogLevel.ERROR)); pipeline.addFirst("bytemetrics", new BytesMetricsHandler(m_bytesMetricsCollector)); pipeline.addLast("decoder", new MqttDecoder()); pipeline.addLast("encoder", MqttEncoder.INSTANCE); @@ -188,27 +196,32 @@ public class NettyAcceptor implements ServerAcceptor { } }); } - + private void initializeWebSocketTransport(final NettyMQTTHandler handler, IConfig props) throws IOException { - LOG.info("Configuring Websocket MQTT transport..."); + LOG.info("Configuring Websocket MQTT transport..."); String webSocketPortProp = props.getProperty(WEB_SOCKET_PORT_PROPERTY_NAME, DISABLED_PORT_BIND); if (DISABLED_PORT_BIND.equals(webSocketPortProp)) { - //Do nothing no WebSocket configured - LOG.info("The property {} has been setted to {}. Websocket MQTT will be disabled.", - BrokerConstants.WEB_SOCKET_PORT_PROPERTY_NAME, DISABLED_PORT_BIND); + // Do nothing no WebSocket configured + LOG.info( + "The property {} has been setted to {}. Websocket MQTT will be disabled.", + BrokerConstants.WEB_SOCKET_PORT_PROPERTY_NAME, + DISABLED_PORT_BIND); return; } int port = Integer.parseInt(webSocketPortProp); - + final MoquetteIdleTimeoutHandler timeoutHandler = new MoquetteIdleTimeoutHandler(); String host = props.getProperty(BrokerConstants.HOST_PROPERTY_NAME); initFactory(host, port, "Websocket MQTT", new PipelineInitializer() { + @Override void init(ChannelPipeline pipeline) { pipeline.addLast(new HttpServerCodec()); pipeline.addLast("aggregator", new HttpObjectAggregator(65536)); - pipeline.addLast("webSocketHandler", new WebSocketServerProtocolHandler("/mqtt", MQTT_SUBPROTOCOL_CSV_LIST)); + pipeline.addLast( + "webSocketHandler", + new WebSocketServerProtocolHandler("/mqtt", MQTT_SUBPROTOCOL_CSV_LIST)); pipeline.addLast("ws2bytebufDecoder", new WebSocketFrameToByteBufDecoder()); pipeline.addLast("bytebuf2wsEncoder", new ByteBufToWebSocketFrameEncoder()); pipeline.addFirst("idleStateHandler", new IdleStateHandler(0, 0, nettyChannelTimeoutSeconds)); @@ -222,14 +235,17 @@ public class NettyAcceptor implements ServerAcceptor { } }); } - - private void initializeSSLTCPTransport(final NettyMQTTHandler handler, IConfig props, final SSLContext sslContext) throws IOException { - LOG.info("Configuring SSL MQTT transport..."); - String sslPortProp = props.getProperty(SSL_PORT_PROPERTY_NAME, DISABLED_PORT_BIND); + + private void initializeSSLTCPTransport(final NettyMQTTHandler handler, IConfig props, final SSLContext sslContext) + throws IOException { + LOG.info("Configuring SSL MQTT transport..."); + String sslPortProp = props.getProperty(SSL_PORT_PROPERTY_NAME, DISABLED_PORT_BIND); if (DISABLED_PORT_BIND.equals(sslPortProp)) { - //Do nothing no SSL configured - LOG.info("The property {} has been setted to {}. SSL MQTT will be disabled.", - BrokerConstants.SSL_PORT_PROPERTY_NAME, DISABLED_PORT_BIND); + // Do nothing no SSL configured + LOG.info( + "The property {} has been setted to {}. SSL MQTT will be disabled.", + BrokerConstants.SSL_PORT_PROPERTY_NAME, + DISABLED_PORT_BIND); return; } @@ -239,14 +255,15 @@ public class NettyAcceptor implements ServerAcceptor { final MoquetteIdleTimeoutHandler timeoutHandler = new MoquetteIdleTimeoutHandler(); String host = props.getProperty(BrokerConstants.HOST_PROPERTY_NAME); String sNeedsClientAuth = props.getProperty(BrokerConstants.NEED_CLIENT_AUTH, "false"); - final boolean needsClientAuth = Boolean.valueOf(sNeedsClientAuth); + final boolean needsClientAuth = Boolean.valueOf(sNeedsClientAuth); initFactory(host, sslPort, "SSL MQTT", new PipelineInitializer() { + @Override void init(ChannelPipeline pipeline) throws Exception { pipeline.addLast("ssl", createSslHandler(sslContext, needsClientAuth)); pipeline.addFirst("idleStateHandler", new IdleStateHandler(0, 0, nettyChannelTimeoutSeconds)); pipeline.addAfter("idleStateHandler", "idleEventHandler", timeoutHandler); - //pipeline.addLast("logger", new LoggingHandler("Netty", LogLevel.ERROR)); + // pipeline.addLast("logger", new LoggingHandler("Netty", LogLevel.ERROR)); pipeline.addFirst("bytemetrics", new BytesMetricsHandler(m_bytesMetricsCollector)); pipeline.addLast("decoder", new MqttDecoder()); pipeline.addLast("encoder", MqttEncoder.INSTANCE); @@ -257,28 +274,34 @@ public class NettyAcceptor implements ServerAcceptor { }); } - private void initializeWSSTransport(final NettyMQTTHandler handler, IConfig props, final SSLContext sslContext) throws IOException { - LOG.info("Configuring secure websocket MQTT transport..."); - String sslPortProp = props.getProperty(WSS_PORT_PROPERTY_NAME, DISABLED_PORT_BIND); + private void initializeWSSTransport(final NettyMQTTHandler handler, IConfig props, final SSLContext sslContext) + throws IOException { + LOG.info("Configuring secure websocket MQTT transport..."); + String sslPortProp = props.getProperty(WSS_PORT_PROPERTY_NAME, DISABLED_PORT_BIND); if (DISABLED_PORT_BIND.equals(sslPortProp)) { - //Do nothing no SSL configured - LOG.info("The property {} has been setted to {}. Secure websocket MQTT will be disabled.", - BrokerConstants.WSS_PORT_PROPERTY_NAME, DISABLED_PORT_BIND); + // Do nothing no SSL configured + LOG.info( + "The property {} has been setted to {}. Secure websocket MQTT will be disabled.", + BrokerConstants.WSS_PORT_PROPERTY_NAME, + DISABLED_PORT_BIND); return; } int sslPort = Integer.parseInt(sslPortProp); final MoquetteIdleTimeoutHandler timeoutHandler = new MoquetteIdleTimeoutHandler(); String host = props.getProperty(BrokerConstants.HOST_PROPERTY_NAME); String sNeedsClientAuth = props.getProperty(BrokerConstants.NEED_CLIENT_AUTH, "false"); - final boolean needsClientAuth = Boolean.valueOf(sNeedsClientAuth); + final boolean needsClientAuth = Boolean.valueOf(sNeedsClientAuth); initFactory(host, sslPort, "Secure websocket", new PipelineInitializer() { + @Override void init(ChannelPipeline pipeline) throws Exception { pipeline.addLast("ssl", createSslHandler(sslContext, needsClientAuth)); pipeline.addLast("httpEncoder", new HttpResponseEncoder()); pipeline.addLast("httpDecoder", new HttpRequestDecoder()); pipeline.addLast("aggregator", new HttpObjectAggregator(65536)); - pipeline.addLast("webSocketHandler", new WebSocketServerProtocolHandler("/mqtt", MQTT_SUBPROTOCOL_CSV_LIST)); + pipeline.addLast( + "webSocketHandler", + new WebSocketServerProtocolHandler("/mqtt", MQTT_SUBPROTOCOL_CSV_LIST)); pipeline.addLast("ws2bytebufDecoder", new WebSocketFrameToByteBufDecoder()); pipeline.addLast("bytebuf2wsEncoder", new ByteBufToWebSocketFrameEncoder()); pipeline.addFirst("idleStateHandler", new IdleStateHandler(0, 0, nettyChannelTimeoutSeconds)); @@ -294,52 +317,56 @@ public class NettyAcceptor implements ServerAcceptor { } public void close() { - LOG.info("Closing Netty acceptor..."); - if (m_workerGroup == null || m_bossGroup == null) { - LOG.error("The Netty acceptor is not initialized."); - throw new IllegalStateException("Invoked close on an Acceptor that wasn't initialized"); - } + LOG.info("Closing Netty acceptor..."); + if (m_workerGroup == null || m_bossGroup == null) { + LOG.error("The Netty acceptor is not initialized."); + throw new IllegalStateException("Invoked close on an Acceptor that wasn't initialized"); + } Future workerWaiter = m_workerGroup.shutdownGracefully(); Future bossWaiter = m_bossGroup.shutdownGracefully(); - - /* - * We shouldn't raise an IllegalStateException if we are interrupted. If - * we did so, the broker is not shut down properly. - */ + + /* + * We shouldn't raise an IllegalStateException if we are interrupted. If we did so, the + * broker is not shut down properly. + */ LOG.info("Waiting for worker and boss event loop groups to terminate..."); try { workerWaiter.await(10, TimeUnit.SECONDS); bossWaiter.await(10, TimeUnit.SECONDS); } catch (InterruptedException iex) { - LOG.warn("An InterruptedException was caught while waiting for event loops to terminate..."); + LOG.warn("An InterruptedException was caught while waiting for event loops to terminate..."); } - + if (!m_workerGroup.isTerminated()) { - LOG.warn("Forcing shutdown of worker event loop..."); - m_workerGroup.shutdownGracefully(0L, 0L, TimeUnit.MILLISECONDS); + LOG.warn("Forcing shutdown of worker event loop..."); + m_workerGroup.shutdownGracefully(0L, 0L, TimeUnit.MILLISECONDS); } - + if (!m_bossGroup.isTerminated()) { - LOG.warn("Forcing shutdown of boss event loop..."); - m_bossGroup.shutdownGracefully(0L, 0L, TimeUnit.MILLISECONDS); + LOG.warn("Forcing shutdown of boss event loop..."); + m_bossGroup.shutdownGracefully(0L, 0L, TimeUnit.MILLISECONDS); } LOG.info("Collecting message metrics..."); MessageMetrics metrics = m_metricsCollector.computeMetrics(); - LOG.info("The metrics have been collected. Read messages = {}, written messages = {}.", - metrics.messagesRead(), metrics.messagesWrote()); + LOG.info( + "The metrics have been collected. Read messages = {}, written messages = {}.", + metrics.messagesRead(), + metrics.messagesWrote()); LOG.info("Collecting bytes metrics..."); BytesMetrics bytesMetrics = m_bytesMetricsCollector.computeMetrics(); - LOG.info("The bytes metrics have been collected. Read bytes = {}, written bytes = {}.", bytesMetrics.readBytes(), - bytesMetrics.wroteBytes()); + LOG.info( + "The bytes metrics have been collected. Read bytes = {}, written bytes = {}.", + bytesMetrics.readBytes(), + bytesMetrics.wroteBytes()); } private ChannelHandler createSslHandler(SSLContext sslContext, boolean needsClientAuth) { SSLEngine sslEngine = sslContext.createSSLEngine(); sslEngine.setUseClientMode(false); - if(needsClientAuth) { - sslEngine.setNeedClientAuth(true); + if (needsClientAuth) { + sslEngine.setNeedClientAuth(true); } return new SslHandler(sslEngine); } diff --git a/broker/src/main/java/io/moquette/server/netty/NettyMQTTHandler.java b/broker/src/main/java/io/moquette/server/netty/NettyMQTTHandler.java index 24e3f094..f1cf944a 100644 --- a/broker/src/main/java/io/moquette/server/netty/NettyMQTTHandler.java +++ b/broker/src/main/java/io/moquette/server/netty/NettyMQTTHandler.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server.netty; import io.moquette.spi.impl.ProtocolProcessor; @@ -22,17 +23,15 @@ import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.handler.codec.mqtt.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import static io.netty.handler.codec.mqtt.MqttQoS.AT_MOST_ONCE; - /** * * @author andrea */ @Sharable public class NettyMQTTHandler extends ChannelInboundHandlerAdapter { - + private static final Logger LOG = LoggerFactory.getLogger(NettyMQTTHandler.class); private final ProtocolProcessor m_processor; @@ -75,22 +74,27 @@ public class NettyMQTTHandler extends ChannelInboundHandlerAdapter { m_processor.processPubAck(ctx.channel(), (MqttPubAckMessage) msg); break; case PINGREQ: - MqttFixedHeader pingHeader = new MqttFixedHeader(MqttMessageType.PINGRESP, false, AT_MOST_ONCE, false, 0); + MqttFixedHeader pingHeader = new MqttFixedHeader( + MqttMessageType.PINGRESP, + false, + AT_MOST_ONCE, + false, + 0); MqttMessage pingResp = new MqttMessage(pingHeader); ctx.writeAndFlush(pingResp); break; } } catch (Throwable ex) { - LOG.error("Exception was caught while processing MQTT message, " + ex.getCause(), ex); - ctx.fireExceptionCaught(ex); + LOG.error("Exception was caught while processing MQTT message, " + ex.getCause(), ex); + ctx.fireExceptionCaught(ex); } } - + @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { String clientID = NettyUtils.clientID(ctx.channel()); if (clientID != null && !clientID.isEmpty()) { - LOG.info("Notifying connection lost event. MqttClientId = {}.", clientID); + LOG.info("Notifying connection lost event. MqttClientId = {}.", clientID); m_processor.processConnectionLost(clientID, ctx.channel()); } ctx.close(); @@ -98,9 +102,12 @@ public class NettyMQTTHandler extends ChannelInboundHandlerAdapter { @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - LOG.error( - "An unexpected exception was caught while processing MQTT message. Closing Netty channel. MqttClientId = {}, cause = {}, errorMessage = {}.", - NettyUtils.clientID(ctx.channel()), cause.getCause(), cause.getMessage()); + LOG.error( + "An unexpected exception was caught while processing MQTT message. " + + "Closing Netty channel. MqttClientId = {}, cause = {}, errorMessage = {}.", + NettyUtils.clientID(ctx.channel()), + cause.getCause(), + cause.getMessage()); ctx.close(); } diff --git a/broker/src/main/java/io/moquette/server/netty/NettyUtils.java b/broker/src/main/java/io/moquette/server/netty/NettyUtils.java index 5d43857a..283d8db9 100644 --- a/broker/src/main/java/io/moquette/server/netty/NettyUtils.java +++ b/broker/src/main/java/io/moquette/server/netty/NettyUtils.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server.netty; import io.moquette.server.Constants; diff --git a/broker/src/main/java/io/moquette/server/netty/metrics/BytesMetrics.java b/broker/src/main/java/io/moquette/server/netty/metrics/BytesMetrics.java index ff19f02a..9a8f9e69 100644 --- a/broker/src/main/java/io/moquette/server/netty/metrics/BytesMetrics.java +++ b/broker/src/main/java/io/moquette/server/netty/metrics/BytesMetrics.java @@ -13,9 +13,11 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server.netty.metrics; public class BytesMetrics { + private long m_readBytes = 0; private long m_wroteBytes = 0; @@ -34,4 +36,4 @@ public class BytesMetrics { public long wroteBytes() { return m_wroteBytes; } -} \ No newline at end of file +} diff --git a/broker/src/main/java/io/moquette/server/netty/metrics/BytesMetricsCollector.java b/broker/src/main/java/io/moquette/server/netty/metrics/BytesMetricsCollector.java index 84a11b2b..45d61e3e 100644 --- a/broker/src/main/java/io/moquette/server/netty/metrics/BytesMetricsCollector.java +++ b/broker/src/main/java/io/moquette/server/netty/metrics/BytesMetricsCollector.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server.netty.metrics; import java.util.concurrent.atomic.AtomicLong; diff --git a/broker/src/main/java/io/moquette/server/netty/metrics/BytesMetricsHandler.java b/broker/src/main/java/io/moquette/server/netty/metrics/BytesMetricsHandler.java index e948b3b8..c5e346d6 100644 --- a/broker/src/main/java/io/moquette/server/netty/metrics/BytesMetricsHandler.java +++ b/broker/src/main/java/io/moquette/server/netty/metrics/BytesMetricsHandler.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server.netty.metrics; import io.netty.buffer.ByteBuf; @@ -30,7 +31,7 @@ public class BytesMetricsHandler extends ChannelDuplexHandler { private BytesMetricsCollector m_collector; public BytesMetricsHandler(BytesMetricsCollector collector) { - m_collector = collector; + m_collector = collector; } @Override @@ -44,21 +45,19 @@ public class BytesMetricsHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { BytesMetrics metrics = ctx.channel().attr(ATTR_KEY_METRICS).get(); - metrics.incrementRead(((ByteBuf)msg).readableBytes()); + metrics.incrementRead(((ByteBuf) msg).readableBytes()); ctx.fireChannelRead(msg); } @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { BytesMetrics metrics = ctx.channel().attr(ATTR_KEY_METRICS).get(); - metrics.incrementWrote(((ByteBuf)msg).writableBytes()); + metrics.incrementWrote(((ByteBuf) msg).writableBytes()); ctx.write(msg, promise); } - @Override - public void close(ChannelHandlerContext ctx, - ChannelPromise promise) throws Exception { + public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { BytesMetrics metrics = ctx.channel().attr(ATTR_KEY_METRICS).get(); m_collector.sumReadBytes(metrics.readBytes()); m_collector.sumWroteBytes(metrics.wroteBytes()); diff --git a/broker/src/main/java/io/moquette/server/netty/metrics/MQTTMessageLogger.java b/broker/src/main/java/io/moquette/server/netty/metrics/MQTTMessageLogger.java index 236e74ab..c4e905d9 100644 --- a/broker/src/main/java/io/moquette/server/netty/metrics/MQTTMessageLogger.java +++ b/broker/src/main/java/io/moquette/server/netty/metrics/MQTTMessageLogger.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server.netty.metrics; import io.moquette.server.netty.NettyUtils; @@ -23,7 +24,6 @@ import io.netty.channel.ChannelPromise; import io.netty.handler.codec.mqtt.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import static io.moquette.spi.impl.Utils.messageId; /** @@ -54,7 +54,11 @@ public class MQTTMessageLogger extends ChannelDuplexHandler { break; case SUBSCRIBE: MqttSubscribeMessage subscribe = (MqttSubscribeMessage) msg; - LOG.info("{} SUBSCRIBE <{}> to topics {}", direction, clientID, subscribe.payload().topicSubscriptions()); + LOG.info( + "{} SUBSCRIBE <{}> to topics {}", + direction, + clientID, + subscribe.payload().topicSubscriptions()); break; case UNSUBSCRIBE: MqttUnsubscribeMessage unsubscribe = (MqttUnsubscribeMessage) msg; diff --git a/broker/src/main/java/io/moquette/server/netty/metrics/MessageMetrics.java b/broker/src/main/java/io/moquette/server/netty/metrics/MessageMetrics.java index fd1dcd90..909784f1 100644 --- a/broker/src/main/java/io/moquette/server/netty/metrics/MessageMetrics.java +++ b/broker/src/main/java/io/moquette/server/netty/metrics/MessageMetrics.java @@ -13,9 +13,11 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server.netty.metrics; public class MessageMetrics { + private long m_messagesRead = 0; private long m_messageWrote = 0; @@ -34,4 +36,4 @@ public class MessageMetrics { public long messagesWrote() { return m_messageWrote; } -} \ No newline at end of file +} diff --git a/broker/src/main/java/io/moquette/server/netty/metrics/MessageMetricsCollector.java b/broker/src/main/java/io/moquette/server/netty/metrics/MessageMetricsCollector.java index ecca02b5..dfab4bbb 100644 --- a/broker/src/main/java/io/moquette/server/netty/metrics/MessageMetricsCollector.java +++ b/broker/src/main/java/io/moquette/server/netty/metrics/MessageMetricsCollector.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server.netty.metrics; import java.util.concurrent.atomic.AtomicLong; @@ -21,6 +22,7 @@ import java.util.concurrent.atomic.AtomicLong; * Collects all the metrics from the various pipeline. */ public class MessageMetricsCollector { + private AtomicLong readMsgs = new AtomicLong(); private AtomicLong wroteMsgs = new AtomicLong(); diff --git a/broker/src/main/java/io/moquette/server/netty/metrics/MessageMetricsHandler.java b/broker/src/main/java/io/moquette/server/netty/metrics/MessageMetricsHandler.java index 7786a5af..dc8f102a 100644 --- a/broker/src/main/java/io/moquette/server/netty/metrics/MessageMetricsHandler.java +++ b/broker/src/main/java/io/moquette/server/netty/metrics/MessageMetricsHandler.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server.netty.metrics; import io.netty.channel.Channel; @@ -29,7 +30,7 @@ public class MessageMetricsHandler extends ChannelDuplexHandler { private MessageMetricsCollector m_collector; public MessageMetricsHandler(MessageMetricsCollector collector) { - m_collector = collector; + m_collector = collector; } @Override @@ -54,10 +55,8 @@ public class MessageMetricsHandler extends ChannelDuplexHandler { ctx.write(msg, promise); } - @Override - public void close(ChannelHandlerContext ctx, - ChannelPromise promise) throws Exception { + public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { MessageMetrics metrics = ctx.channel().attr(ATTR_KEY_METRICS).get(); m_collector.sumReadMessages(metrics.messagesRead()); m_collector.sumWroteMessages(metrics.messagesWrote()); diff --git a/broker/src/main/java/io/moquette/spi/ClientSession.java b/broker/src/main/java/io/moquette/spi/ClientSession.java index 0c225f13..3b2bf3a6 100644 --- a/broker/src/main/java/io/moquette/spi/ClientSession.java +++ b/broker/src/main/java/io/moquette/spi/ClientSession.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi; import io.moquette.spi.ISessionsStore.ClientTopicCouple; @@ -20,7 +21,6 @@ import io.moquette.spi.impl.subscriptions.Subscription; import io.moquette.spi.impl.subscriptions.SubscriptionsStore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.util.HashSet; import java.util.Set; import java.util.concurrent.BlockingQueue; @@ -55,10 +55,11 @@ public class ClientSession { private volatile boolean cleanSession; -// private BlockingQueue m_queueToPublish = new ArrayBlockingQueue<>(Constants.MAX_MESSAGE_QUEUE); + // private BlockingQueue m_queueToPublish = new + // ArrayBlockingQueue<>(Constants.MAX_MESSAGE_QUEUE); public ClientSession(String clientID, IMessagesStore messagesStore, ISessionsStore sessionsStore, - boolean cleanSession) { + boolean cleanSession) { this.clientID = clientID; this.messagesStore = messagesStore; this.m_sessionsStore = sessionsStore; @@ -66,12 +67,12 @@ public class ClientSession { } /** - * Return the list of persisted publishes for the given clientID. - * For QoS1 and QoS2 with clean session flag, this method return the list of - * missed publish events while the client was disconnected. + * Return the list of persisted publishes for the given clientID. For QoS1 and QoS2 with clean + * session flag, this method return the list of missed publish events while the client was + * disconnected. * * @return the list of messages to be delivered for client related to the session. - * */ + */ public BlockingQueue queue() { LOG.info("Retrieving stored messages. MqttClientId = {}.", clientID); return this.m_sessionsStore.queue(clientID); @@ -79,26 +80,35 @@ public class ClientSession { @Override public String toString() { - return "ClientSession{clientID='" + clientID + '\'' +"}"; + return "ClientSession{clientID='" + clientID + '\'' + "}"; } public boolean subscribe(Subscription newSubscription) { - LOG.info("Adding new subscription. MqttClientId = {}, topics = {}, qos = {}.", newSubscription.getClientId(), - newSubscription.getTopicFilter(), newSubscription.getRequestedQos()); + LOG.info( + "Adding new subscription. MqttClientId = {}, topics = {}, qos = {}.", + newSubscription.getClientId(), + newSubscription.getTopicFilter(), + newSubscription.getRequestedQos()); boolean validTopic = SubscriptionsStore.validate(newSubscription.getTopicFilter()); if (!validTopic) { - LOG.warn("The topic filter is not valid. MqttClientId = {}, topics = {}.", newSubscription.getClientId(), - newSubscription.getTopicFilter()); - //send SUBACK with 0x80 for this topic filter + LOG.warn( + "The topic filter is not valid. MqttClientId = {}, topics = {}.", + newSubscription.getClientId(), + newSubscription.getTopicFilter()); + // send SUBACK with 0x80 for this topic filter return false; } ClientTopicCouple matchingCouple = new ClientTopicCouple(this.clientID, newSubscription.getTopicFilter()); Subscription existingSub = m_sessionsStore.getSubscription(matchingCouple); - //update the selected subscriptions if not present or if has a greater qos + // update the selected subscriptions if not present or if has a greater qos if (existingSub == null || existingSub.getRequestedQos().value() < newSubscription.getRequestedQos().value()) { if (existingSub != null) { - LOG.info("The subscription already existed with a lower QoS value. It will be updated. MqttClientId = {}, topics = {}, existingQos = {}, newQos = {}.", - newSubscription.getClientId(), newSubscription.getTopicFilter(), existingSub.getRequestedQos(), + LOG.info( + "The subscription already existed with a lower QoS value. It will be updated. " + + "MqttClientId = {}, topics = {}, existingQos = {}, newQos = {}.", + newSubscription.getClientId(), + newSubscription.getTopicFilter(), + existingSub.getRequestedQos(), newSubscription.getRequestedQos()); subscriptions.remove(newSubscription); } @@ -123,17 +133,16 @@ public class ClientSession { public void disconnect() { if (this.cleanSession) { LOG.info("The client has disconnected. Removing its subscriptions. MqttClientId = {}.", clientID); - //cleanup topic subscriptions + // cleanup topic subscriptions cleanSession(); } - } public void cleanSession() { LOG.info("Wiping existing subscriptions. MqttClientId = {}.", this.clientID); m_sessionsStore.wipeSubscriptions(this.clientID); - //remove also the messages stored of type QoS1/2 + // remove also the messages stored of type QoS1/2 LOG.info("Removing stored messages with QoS 1 and 2. MqttClientId = {}.", this.clientID); messagesStore.dropMessagesInSession(this.clientID); } @@ -152,7 +161,7 @@ public class ClientSession { } public void inFlightAcknowledged(int messageID) { - if (LOG.isTraceEnabled()) + if (LOG.isTraceEnabled()) LOG.trace("Acknowledging inflight, clientID <{}> messageID {}", this.clientID, messageID); m_sessionsStore.inFlightAck(this.clientID, messageID); } @@ -170,8 +179,10 @@ public class ClientSession { /** * Enqueue a message to be sent to the client. - * @param message the message to enqueue. - * */ + * + * @param message + * the message to enqueue. + */ public void enqueue(IMessagesStore.StoredMessage message) { this.m_sessionsStore.queue(this.clientID).add(message); } @@ -205,4 +216,4 @@ public class ClientSession { return m_sessionsStore.getInflightMessagesNo(clientID); } -} \ No newline at end of file +} diff --git a/broker/src/main/java/io/moquette/spi/IMatchingCondition.java b/broker/src/main/java/io/moquette/spi/IMatchingCondition.java index 0a2cf55b..24a73eb9 100644 --- a/broker/src/main/java/io/moquette/spi/IMatchingCondition.java +++ b/broker/src/main/java/io/moquette/spi/IMatchingCondition.java @@ -13,11 +13,12 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi; /** */ public interface IMatchingCondition { + boolean match(String key); } - diff --git a/broker/src/main/java/io/moquette/spi/IMessagesStore.java b/broker/src/main/java/io/moquette/spi/IMessagesStore.java index 7693b33b..e89e073d 100644 --- a/broker/src/main/java/io/moquette/spi/IMessagesStore.java +++ b/broker/src/main/java/io/moquette/spi/IMessagesStore.java @@ -13,12 +13,12 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.handler.codec.mqtt.MqttQoS; - import java.io.Serializable; import java.nio.ByteBuffer; import java.util.Collection; @@ -29,13 +29,14 @@ import java.util.Collection; public interface IMessagesStore { class StoredMessage implements Serializable { + private static final long serialVersionUID = 1755296138639817304L; final MqttQoS m_qos; final byte[] m_payload; final String m_topic; private boolean m_retained; private String m_clientID; - //Optional attribute, available only fo QoS 1 and 2 + // Optional attribute, available only fo QoS 1 and 2 private Integer m_msgID; private MessageGUID m_guid; @@ -95,41 +96,42 @@ public interface IMessagesStore { @Override public String toString() { - return "PublishEvent{" + - "m_msgID=" + m_msgID + - ", clientID='" + m_clientID + '\'' + - ", m_retain=" + m_retained + - ", m_qos=" + m_qos + - ", m_topic='" + m_topic + '\'' + - '}'; + return "PublishEvent{" + "m_msgID=" + m_msgID + ", clientID='" + m_clientID + '\'' + ", m_retain=" + + m_retained + ", m_qos=" + m_qos + ", m_topic='" + m_topic + '\'' + '}'; } } /** * Used to initialize all persistent store structures - * */ + */ void initStore(); /** - * Persist the message. - * If the message is empty then the topic is cleaned, else it's stored. - * @param topic for the retained. - * @param guid of the message to mark as retained. + * Persist the message. If the message is empty then the topic is cleaned, else it's stored. + * + * @param topic + * for the retained. + * @param guid + * of the message to mark as retained. */ void storeRetained(String topic, MessageGUID guid); /** * Return a list of retained messages that satisfy the condition. - * @param condition the condition to match during the search. + * + * @param condition + * the condition to match during the search. * @return the collection of matching messages. */ Collection searchMatching(IMatchingCondition condition); /** * Persist the message. - * @param storedMessage the message to store for future usage. + * + * @param storedMessage + * the message to store for future usage. * @return the unique id in the storage (guid). - * */ + */ MessageGUID storePublishForFuture(StoredMessage storedMessage); void dropMessagesInSession(String clientID); diff --git a/broker/src/main/java/io/moquette/spi/IMessaging.java b/broker/src/main/java/io/moquette/spi/IMessaging.java index d91a2c43..223cd572 100644 --- a/broker/src/main/java/io/moquette/spi/IMessaging.java +++ b/broker/src/main/java/io/moquette/spi/IMessaging.java @@ -13,14 +13,14 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi; /** * Callback interface used to be notified of some events from the input event queue. - * - * It's the abstraction of the messaging stuff attached in after the front protocol - * parsing stuff. - * + * + * It's the abstraction of the messaging stuff attached in after the front protocol parsing stuff. + * * @author andrea */ public interface IMessaging { diff --git a/broker/src/main/java/io/moquette/spi/ISessionsStore.java b/broker/src/main/java/io/moquette/spi/ISessionsStore.java index 422b02f3..3d0cd551 100644 --- a/broker/src/main/java/io/moquette/spi/ISessionsStore.java +++ b/broker/src/main/java/io/moquette/spi/ISessionsStore.java @@ -13,12 +13,12 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi; import java.util.Collection; import java.util.List; import java.util.concurrent.BlockingQueue; - import io.moquette.spi.IMessagesStore.StoredMessage; import io.moquette.spi.impl.subscriptions.Subscription; @@ -30,6 +30,7 @@ import io.moquette.spi.impl.subscriptions.Subscription; public interface ISessionsStore { class ClientTopicCouple { + public final String topicFilter; public final String clientID; @@ -40,12 +41,15 @@ public interface ISessionsStore { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; ClientTopicCouple that = (ClientTopicCouple) o; - if (topicFilter != null ? !topicFilter.equals(that.topicFilter) : that.topicFilter != null) return false; + if (topicFilter != null ? !topicFilter.equals(that.topicFilter) : that.topicFilter != null) + return false; return !(clientID != null ? !clientID.equals(that.clientID) : that.clientID != null); } @@ -58,10 +62,7 @@ public interface ISessionsStore { @Override public String toString() { - return "ClientTopicCouple{" + - "topicFilter='" + topicFilter + '\'' + - ", clientID='" + clientID + '\'' + - '}'; + return "ClientTopicCouple{" + "topicFilter='" + topicFilter + '\'' + ", clientID='" + clientID + '\'' + '}'; } } @@ -72,41 +73,50 @@ public interface ISessionsStore { /** * Add a new subscription to the session - * @param newSubscription the subscription to add. + * + * @param newSubscription + * the subscription to add. */ void addNewSubscription(Subscription newSubscription); /** * Removed a specific subscription - * @param topic the topic of the subscription. - * @param clientID the session client. - * */ + * + * @param topic + * the topic of the subscription. + * @param clientID + * the session client. + */ void removeSubscription(String topic, String clientID); /** * Remove all the subscriptions of the session - * @param sessionID the client ID + * + * @param sessionID + * the client ID */ void wipeSubscriptions(String sessionID); /** * Return all topic filters to recreate the subscription tree. - * */ + */ List listAllSubscriptions(); /** - * @param couple the subscription descriptor. + * @param couple + * the subscription descriptor. * @return the subscription stored by clientID and topicFilter, if any else null; - * */ + */ Subscription getSubscription(ClientTopicCouple couple); - + /* * @return all subscriptions stored. */ List getSubscriptions(); /** - * @param clientID the session client ID. + * @param clientID + * the session client ID. * @return true iff there are subscriptions persisted with clientID */ boolean contains(String clientID); @@ -114,13 +124,15 @@ public interface ISessionsStore { ClientSession createNewSession(String clientID, boolean cleanSession); /** - * @param clientID the client owning the session. + * @param clientID + * the client owning the session. * @return the session for the given clientID, null if not found. - * */ + */ ClientSession sessionForClient(String clientID); - + /** * Returns all the sessions + * * @return */ Collection getAllSessions(); @@ -129,24 +141,32 @@ public interface ISessionsStore { /** * Save the binding messageID, clientID - guid - * @param clientID the client ID - * @param messageID the message ID - * @param guid the uuid of the message to mark as inflight. - * */ + * + * @param clientID + * the client ID + * @param messageID + * the message ID + * @param guid + * the uuid of the message to mark as inflight. + */ void inFlight(String clientID, int messageID, MessageGUID guid); /** * Return the next valid packetIdentifier for the given client session. - * @param clientID the clientID requesting next packet id. + * + * @param clientID + * the clientID requesting next packet id. * @return the next valid id. - * */ + */ int nextPacketID(String clientID); /** * List the guids for retained messages for the session - * @param clientID the client ID owning the queue. + * + * @param clientID + * the client ID owning the queue. * @return the list of queue message UUIDs. - * */ + */ BlockingQueue queue(String clientID); void dropQueue(String clientID); @@ -154,19 +174,21 @@ public interface ISessionsStore { void moveInFlightToSecondPhaseAckWaiting(String clientID, int messageID); /** - * @param clientID the client ID accessing the second phase. - * @param messageID the message ID that reached the second phase. + * @param clientID + * the client ID accessing the second phase. + * @param messageID + * the message ID that reached the second phase. * @return the guid of message just acked. - * */ + */ MessageGUID secondPhaseAcknowledged(String clientID, int messageID); MessageGUID mapToGuid(String clientID, int messageID); - + StoredMessage getInflightMessage(String clientID, int messageID); /** * Returns the number of inflight messages for the given client ID - * + * * @param clientID * @return */ @@ -174,16 +196,15 @@ public interface ISessionsStore { /** * Returns the size of the session queue for the given client ID - * + * * @param clientID * @return */ int getPendingPublishMessagesNo(String clientID); /** - * Returns the number of second-phase ACK pending messages for the given - * client ID - * + * Returns the number of second-phase ACK pending messages for the given client ID + * * @param clientID * @return */ diff --git a/broker/src/main/java/io/moquette/spi/MessageGUID.java b/broker/src/main/java/io/moquette/spi/MessageGUID.java index 96c70df9..b933ec60 100644 --- a/broker/src/main/java/io/moquette/spi/MessageGUID.java +++ b/broker/src/main/java/io/moquette/spi/MessageGUID.java @@ -13,16 +13,18 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi; import java.io.Serializable; /** * Value object for GUIDs of messages. - * */ + */ public class MessageGUID implements Serializable { + private static final long serialVersionUID = 4315161987111542406L; - private final String guid; + private final String guid; public MessageGUID(String guid) { this.guid = guid; @@ -30,13 +32,14 @@ public class MessageGUID implements Serializable { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; MessageGUID that = (MessageGUID) o; return guid != null ? guid.equals(that.guid) : that.guid == null; - } @Override @@ -46,8 +49,6 @@ public class MessageGUID implements Serializable { @Override public String toString() { - return "MessageGUID{" + - "guid='" + guid + '\'' + - '}'; + return "MessageGUID{" + "guid='" + guid + '\'' + '}'; } -} \ No newline at end of file +} diff --git a/broker/src/main/java/io/moquette/spi/impl/BrokerInterceptor.java b/broker/src/main/java/io/moquette/spi/impl/BrokerInterceptor.java index bab6378e..7d2c1086 100644 --- a/broker/src/main/java/io/moquette/spi/impl/BrokerInterceptor.java +++ b/broker/src/main/java/io/moquette/spi/impl/BrokerInterceptor.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl; import io.moquette.BrokerConstants; @@ -25,7 +26,6 @@ import io.netty.handler.codec.mqtt.MqttConnectMessage; import io.netty.handler.codec.mqtt.MqttPublishMessage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.util.HashMap; import java.util.List; import java.util.Map; @@ -33,7 +33,6 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; - import static io.moquette.logging.LoggingUtils.getInterceptorIds; /** @@ -47,56 +46,60 @@ final class BrokerInterceptor implements Interceptor { private final Map, List> handlers; private final ExecutorService executor; - private BrokerInterceptor(int poolSize, List handlers) { - LOG.info("Initializing broker interceptor. InterceptorIds = {}.", getInterceptorIds(handlers)); - this.handlers = new HashMap<>(); - for (Class messageType : InterceptHandler.ALL_MESSAGE_TYPES) { - this.handlers.put(messageType, new CopyOnWriteArrayList()); - } - for (InterceptHandler handler : handlers) { - this.addInterceptHandler(handler); - } - executor = Executors.newFixedThreadPool(poolSize); - } - - /** - * Configures a broker interceptor, with a thread pool of one thread. - * @param handlers - */ - public BrokerInterceptor(List handlers) { - this(1, handlers); - } - - /** - * Configures a broker interceptor using the pool size specified in the - * IConfig argument. - */ - public BrokerInterceptor(IConfig props, List handlers) { - this(Integer.parseInt(props.getProperty(BrokerConstants.BROKER_INTERCEPTOR_THREAD_POOL_SIZE, "1")), handlers); - } + private BrokerInterceptor(int poolSize, List handlers) { + LOG.info("Initializing broker interceptor. InterceptorIds = {}.", getInterceptorIds(handlers)); + this.handlers = new HashMap<>(); + for (Class messageType : InterceptHandler.ALL_MESSAGE_TYPES) { + this.handlers.put(messageType, new CopyOnWriteArrayList()); + } + for (InterceptHandler handler : handlers) { + this.addInterceptHandler(handler); + } + executor = Executors.newFixedThreadPool(poolSize); + } + + /** + * Configures a broker interceptor, with a thread pool of one thread. + * + * @param handlers + */ + public BrokerInterceptor(List handlers) { + this(1, handlers); + } + + /** + * Configures a broker interceptor using the pool size specified in the IConfig argument. + */ + public BrokerInterceptor(IConfig props, List handlers) { + this(Integer.parseInt(props.getProperty(BrokerConstants.BROKER_INTERCEPTOR_THREAD_POOL_SIZE, "1")), handlers); + } /** * Shutdown graciously the executor service */ - void stop() { - LOG.info("Shutting down interceptor thread pool..."); - executor.shutdown(); - try { - LOG.info("Waiting for thread pool tasks to terminate..."); - executor.awaitTermination(10L, TimeUnit.SECONDS); - } catch (InterruptedException e) {} - if (!executor.isTerminated()) { - LOG.warn("Forcing shutdown of interceptor thread pool..."); - executor.shutdownNow(); - } - } + void stop() { + LOG.info("Shutting down interceptor thread pool..."); + executor.shutdown(); + try { + LOG.info("Waiting for thread pool tasks to terminate..."); + executor.awaitTermination(10L, TimeUnit.SECONDS); + } catch (InterruptedException e) { + } + if (!executor.isTerminated()) { + LOG.warn("Forcing shutdown of interceptor thread pool..."); + executor.shutdownNow(); + } + } @Override public void notifyClientConnected(final MqttConnectMessage msg) { for (final InterceptHandler handler : this.handlers.get(InterceptConnectMessage.class)) { - LOG.debug("Sending MQTT CONNECT message to interceptor. MqttClientId = {}, interceptorId = {}.", - msg.payload().clientIdentifier(), handler.getID()); + LOG.debug( + "Sending MQTT CONNECT message to interceptor. MqttClientId = {}, interceptorId = {}.", + msg.payload().clientIdentifier(), + handler.getID()); executor.execute(new Runnable() { + @Override public void run() { handler.onConnect(new InterceptConnectMessage(msg)); @@ -106,11 +109,16 @@ final class BrokerInterceptor implements Interceptor { } @Override - public void notifyClientDisconnected(final String clientID, final String username ) { + public void notifyClientDisconnected(final String clientID, final String username) { for (final InterceptHandler handler : this.handlers.get(InterceptDisconnectMessage.class)) { - LOG.debug("Notifying MQTT client disconnection to interceptor. MqttClientId = {}, username = {}, " + - "interceptorId = {}.", clientID, username, handler.getID()); + LOG.debug( + "Notifying MQTT client disconnection to interceptor. MqttClientId = {}, username = {}, " + + "interceptorId = {}.", + clientID, + username, + handler.getID()); executor.execute(new Runnable() { + @Override public void run() { handler.onDisconnect(new InterceptDisconnectMessage(clientID, username)); @@ -122,9 +130,14 @@ final class BrokerInterceptor implements Interceptor { @Override public void notifyClientConnectionLost(final String clientID, final String username) { for (final InterceptHandler handler : this.handlers.get(InterceptConnectionLostMessage.class)) { - LOG.debug("Notifying unexpected MQTT client disconnection to interceptor. MqttClientId = {}, " + - "username = {}, interceptorId = {}.", clientID, username, handler.getID()); + LOG.debug( + "Notifying unexpected MQTT client disconnection to interceptor. MqttClientId = {}, " + + "username = {}, interceptorId = {}.", + clientID, + username, + handler.getID()); executor.execute(new Runnable() { + @Override public void run() { handler.onConnectionLost(new InterceptConnectionLostMessage(clientID, username)); @@ -138,9 +151,15 @@ final class BrokerInterceptor implements Interceptor { int messageId = msg.variableHeader().messageId(); String topic = msg.variableHeader().topicName(); for (final InterceptHandler handler : this.handlers.get(InterceptPublishMessage.class)) { - LOG.debug("Notifying MQTT PUBLISH message to interceptor. MqttClientId = {}, messageId = {}, topic = {}, " + - "interceptorId = {}.", clientID, messageId, topic, handler.getID()); + LOG.debug( + "Notifying MQTT PUBLISH message to interceptor. MqttClientId = {}, messageId = {}, topic = {}, " + + "interceptorId = {}.", + clientID, + messageId, + topic, + handler.getID()); executor.execute(new Runnable() { + @Override public void run() { handler.onPublish(new InterceptPublishMessage(msg, clientID, username)); @@ -152,9 +171,14 @@ final class BrokerInterceptor implements Interceptor { @Override public void notifyTopicSubscribed(final Subscription sub, final String username) { for (final InterceptHandler handler : this.handlers.get(InterceptSubscribeMessage.class)) { - LOG.debug("Notifying MQTT SUBSCRIBE message to interceptor. MqttClientId = {}, topicFilter = {}, " + - "interceptorId = {}.", sub.getClientId(), sub.getTopicFilter(), handler.getID()); + LOG.debug( + "Notifying MQTT SUBSCRIBE message to interceptor. MqttClientId = {}, topicFilter = {}, " + + "interceptorId = {}.", + sub.getClientId(), + sub.getTopicFilter(), + handler.getID()); executor.execute(new Runnable() { + @Override public void run() { handler.onSubscribe(new InterceptSubscribeMessage(sub, username)); @@ -166,9 +190,14 @@ final class BrokerInterceptor implements Interceptor { @Override public void notifyTopicUnsubscribed(final String topic, final String clientID, final String username) { for (final InterceptHandler handler : this.handlers.get(InterceptUnsubscribeMessage.class)) { - LOG.debug("Notifying MQTT UNSUBSCRIBE message to interceptor. MqttClientId = {}, topic = {}, " + - "interceptorId = {}.", clientID, topic, handler.getID()); + LOG.debug( + "Notifying MQTT UNSUBSCRIBE message to interceptor. MqttClientId = {}, topic = {}, " + + "interceptorId = {}.", + clientID, + topic, + handler.getID()); executor.execute(new Runnable() { + @Override public void run() { handler.onUnsubscribe(new InterceptUnsubscribeMessage(topic, clientID, username)); @@ -177,13 +206,18 @@ final class BrokerInterceptor implements Interceptor { } } - @Override - public void notifyMessageAcknowledged( final InterceptAcknowledgedMessage msg ) { + @Override + public void notifyMessageAcknowledged(final InterceptAcknowledgedMessage msg) { for (final InterceptHandler handler : this.handlers.get(InterceptAcknowledgedMessage.class)) { - LOG.debug("Notifying MQTT ACK message to interceptor. MqttClientId = {}, messageId = {}, topic = {}, " + - "interceptorId = {}.", - msg.getMsg().getClientID(), msg.getMsg().getMessageID(), msg.getTopic(), handler.getID()); + LOG.debug( + "Notifying MQTT ACK message to interceptor. MqttClientId = {}, messageId = {}, topic = {}, " + + "interceptorId = {}.", + msg.getMsg().getClientID(), + msg.getMsg().getMessageID(), + msg.getTopic(), + handler.getID()); executor.execute(new Runnable() { + @Override public void run() { handler.onMessageAcknowledged(msg); @@ -192,31 +226,35 @@ final class BrokerInterceptor implements Interceptor { } } - @Override - public void addInterceptHandler(InterceptHandler interceptHandler) { - Class[] interceptedMessageTypes = getInterceptedMessageTypes(interceptHandler); - LOG.info("Adding MQTT message interceptor. InterceptorId = {}, handledMessageTypes = {}.", - interceptHandler.getID(), interceptedMessageTypes); - for (Class interceptMessageType : interceptedMessageTypes) { - this.handlers.get(interceptMessageType).add(interceptHandler); - } - } - - @Override - public void removeInterceptHandler(InterceptHandler interceptHandler) { - Class[] interceptedMessageTypes = getInterceptedMessageTypes(interceptHandler); - LOG.info("Removing MQTT message interceptor. InterceptorId = {}, handledMessageTypes = {}.", - interceptHandler.getID(), interceptedMessageTypes); - for (Class interceptMessageType : interceptedMessageTypes) { - this.handlers.get(interceptMessageType).remove(interceptHandler); - } + @Override + public void addInterceptHandler(InterceptHandler interceptHandler) { + Class[] interceptedMessageTypes = getInterceptedMessageTypes(interceptHandler); + LOG.info( + "Adding MQTT message interceptor. InterceptorId = {}, handledMessageTypes = {}.", + interceptHandler.getID(), + interceptedMessageTypes); + for (Class interceptMessageType : interceptedMessageTypes) { + this.handlers.get(interceptMessageType).add(interceptHandler); + } } - private static Class[] getInterceptedMessageTypes(InterceptHandler interceptHandler) { - Class interceptedMessageTypes[] = interceptHandler.getInterceptedMessageTypes(); - if (interceptedMessageTypes == null) { - return InterceptHandler.ALL_MESSAGE_TYPES; - } - return interceptedMessageTypes; - } + @Override + public void removeInterceptHandler(InterceptHandler interceptHandler) { + Class[] interceptedMessageTypes = getInterceptedMessageTypes(interceptHandler); + LOG.info( + "Removing MQTT message interceptor. InterceptorId = {}, handledMessageTypes = {}.", + interceptHandler.getID(), + interceptedMessageTypes); + for (Class interceptMessageType : interceptedMessageTypes) { + this.handlers.get(interceptMessageType).remove(interceptHandler); + } + } + + private static Class[] getInterceptedMessageTypes(InterceptHandler interceptHandler) { + Class[] interceptedMessageTypes = interceptHandler.getInterceptedMessageTypes(); + if (interceptedMessageTypes == null) { + return InterceptHandler.ALL_MESSAGE_TYPES; + } + return interceptedMessageTypes; + } } diff --git a/broker/src/main/java/io/moquette/spi/impl/DebugUtils.java b/broker/src/main/java/io/moquette/spi/impl/DebugUtils.java index 831dc74b..4c403275 100644 --- a/broker/src/main/java/io/moquette/spi/impl/DebugUtils.java +++ b/broker/src/main/java/io/moquette/spi/impl/DebugUtils.java @@ -13,10 +13,10 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl; import io.netty.buffer.ByteBuf; - import java.nio.ByteBuffer; /** @@ -24,6 +24,7 @@ import java.nio.ByteBuffer; * @author andrea */ class DebugUtils { + static String payload2Str(ByteBuffer content) { byte[] b = new byte[content.remaining()]; content.mark(); @@ -33,7 +34,7 @@ class DebugUtils { } static String payload2Str(ByteBuf content) { - //byte[] b = new byte[content.readableBytes()]; + // byte[] b = new byte[content.readableBytes()]; return new String(content.copy().array()); } } diff --git a/broker/src/main/java/io/moquette/spi/impl/InternalRepublisher.java b/broker/src/main/java/io/moquette/spi/impl/InternalRepublisher.java index 13d3e686..7db968a0 100644 --- a/broker/src/main/java/io/moquette/spi/impl/InternalRepublisher.java +++ b/broker/src/main/java/io/moquette/spi/impl/InternalRepublisher.java @@ -1,5 +1,5 @@ -package io.moquette.spi.impl; +package io.moquette.spi.impl; import io.moquette.spi.ClientSession; import io.moquette.spi.IMessagesStore; @@ -7,7 +7,6 @@ import io.netty.buffer.ByteBuf; import io.netty.handler.codec.mqtt.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -25,15 +24,20 @@ class InternalRepublisher { void publishRetained(ClientSession targetSession, Collection messages) { for (IMessagesStore.StoredMessage storedMsg : messages) { - //fire as retained the message + // fire as retained the message Integer packetID = storedMsg.getQos() == MqttQoS.AT_MOST_ONCE ? null : targetSession.nextPacketId(); if (packetID != null) { - LOG.debug("Adding message to inflight zone. MqttClientId = {}, packetId = {}, messageId = {}, topic = {}.", - targetSession.clientID, packetID, storedMsg.getMessageID(), storedMsg.getTopic()); + LOG.debug( + "Adding message to inflight zone. " + + "MqttClientId = {}, packetId = {}, messageId = {}, topic = {}.", + targetSession.clientID, + packetID, + storedMsg.getMessageID(), + storedMsg.getTopic()); targetSession.inFlightAckWaiting(storedMsg.getGuid(), packetID); } MqttPublishMessage publishMsg = retainedPublish(storedMsg); - //set the PacketIdentifier only for QoS > 0 + // set the PacketIdentifier only for QoS > 0 if (publishMsg.fixedHeader().qosLevel() != MqttQoS.AT_MOST_ONCE) { publishMsg = retainedPublish(storedMsg, packetID); } @@ -41,19 +45,21 @@ class InternalRepublisher { } } - - void publishStored(ClientSession clientSession, BlockingQueue publishedEvents) { List storedPublishes = new ArrayList<>(); publishedEvents.drainTo(storedPublishes); for (IMessagesStore.StoredMessage pubEvt : storedPublishes) { - //put in flight zone - LOG.debug("Adding message ot inflight zone. MqttClientId = {}, guid = {}, messageId = {}, topic = {}.", - clientSession.clientID, pubEvt.getGuid(), pubEvt.getMessageID(), pubEvt.getTopic()); + // put in flight zone + LOG.debug( + "Adding message ot inflight zone. MqttClientId = {}, guid = {}, messageId = {}, topic = {}.", + clientSession.clientID, + pubEvt.getGuid(), + pubEvt.getMessageID(), + pubEvt.getTopic()); clientSession.inFlightAckWaiting(pubEvt.getGuid(), pubEvt.getMessageID()); MqttPublishMessage publishMsg = notRetainedPublish(pubEvt); - //set the PacketIdentifier only for QoS > 0 + // set the PacketIdentifier only for QoS > 0 if (publishMsg.fixedHeader().qosLevel() != MqttQoS.AT_MOST_ONCE) { publishMsg = notRetainedPublish(pubEvt, pubEvt.getMessageID()); } @@ -62,22 +68,43 @@ class InternalRepublisher { } private MqttPublishMessage notRetainedPublish(IMessagesStore.StoredMessage storedMessage, Integer messageID) { - return createPublishForQos(storedMessage.getTopic(), storedMessage.getQos(), storedMessage.getMessage(), false, messageID); + return createPublishForQos( + storedMessage.getTopic(), + storedMessage.getQos(), + storedMessage.getMessage(), + false, + messageID); } private MqttPublishMessage notRetainedPublish(IMessagesStore.StoredMessage storedMessage) { - return createPublishForQos(storedMessage.getTopic(), storedMessage.getQos(), storedMessage.getMessage(), false, 0); + return createPublishForQos( + storedMessage.getTopic(), + storedMessage.getQos(), + storedMessage.getMessage(), + false, + 0); } private MqttPublishMessage retainedPublish(IMessagesStore.StoredMessage storedMessage) { - return createPublishForQos(storedMessage.getTopic(), storedMessage.getQos(), storedMessage.getMessage(), true, 0); + return createPublishForQos( + storedMessage.getTopic(), + storedMessage.getQos(), + storedMessage.getMessage(), + true, + 0); } private MqttPublishMessage retainedPublish(IMessagesStore.StoredMessage storedMessage, Integer packetID) { - return createPublishForQos(storedMessage.getTopic(), storedMessage.getQos(), storedMessage.getMessage(), true, packetID); + return createPublishForQos( + storedMessage.getTopic(), + storedMessage.getQos(), + storedMessage.getMessage(), + true, + packetID); } - public static MqttPublishMessage createPublishForQos(String topic, MqttQoS qos, ByteBuf message, boolean retained, int messageId) { + public static MqttPublishMessage createPublishForQos(String topic, MqttQoS qos, ByteBuf message, boolean retained, + int messageId) { MqttFixedHeader fixedHeader = new MqttFixedHeader(MqttMessageType.PUBLISH, false, qos, retained, 0); MqttPublishVariableHeader varHeader = new MqttPublishVariableHeader(topic, messageId); return new MqttPublishMessage(fixedHeader, varHeader, message); diff --git a/broker/src/main/java/io/moquette/spi/impl/MessagesPublisher.java b/broker/src/main/java/io/moquette/spi/impl/MessagesPublisher.java index 941ee257..7d03cb36 100644 --- a/broker/src/main/java/io/moquette/spi/impl/MessagesPublisher.java +++ b/broker/src/main/java/io/moquette/spi/impl/MessagesPublisher.java @@ -1,3 +1,4 @@ + package io.moquette.spi.impl; import io.moquette.server.ConnectionDescriptorStore; @@ -10,9 +11,7 @@ import io.netty.buffer.ByteBuf; import io.netty.handler.codec.mqtt.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.util.List; - import static io.moquette.spi.impl.ProtocolProcessor.lowerQosToTheSubscriptionDesired; class MessagesPublisher { @@ -24,7 +23,7 @@ class MessagesPublisher { private final PersistentQueueMessageSender messageSender; public MessagesPublisher(ConnectionDescriptorStore connectionDescriptors, ISessionsStore sessionsStore, - IMessagesStore messagesStore, PersistentQueueMessageSender messageSender) { + IMessagesStore messagesStore, PersistentQueueMessageSender messageSender) { this.connectionDescriptors = connectionDescriptors; this.m_sessionsStore = sessionsStore; this.m_messagesStore = messagesStore; @@ -35,7 +34,8 @@ class MessagesPublisher { return notRetainedPublishWithMessageId(topic, qos, message, 0); } - private static MqttPublishMessage notRetainedPublishWithMessageId(String topic, MqttQoS qos, ByteBuf message, int messageId) { + private static MqttPublishMessage notRetainedPublishWithMessageId(String topic, MqttQoS qos, ByteBuf message, + int messageId) { MqttFixedHeader fixedHeader = new MqttFixedHeader(MqttMessageType.PUBLISH, false, qos, false, 0); MqttPublishVariableHeader varHeader = new MqttPublishVariableHeader(topic, messageId); return new MqttPublishMessage(fixedHeader, varHeader, message); @@ -46,38 +46,47 @@ class MessagesPublisher { final MqttQoS publishingQos = pubMsg.getQos(); final ByteBuf origMessage = pubMsg.getMessage(); - //if QoS 1 or 2 store the message - //TODO perhaps this block is not needed. + // if QoS 1 or 2 store the message + // TODO perhaps this block is not needed. MessageGUID guid = null; if (publishingQos != MqttQoS.AT_MOST_ONCE) { guid = m_messagesStore.storePublishForFuture(pubMsg); } - + for (final Subscription sub : topicMatchingSubscriptions) { MqttQoS qos = lowerQosToTheSubscriptionDesired(sub, publishingQos); ClientSession targetSession = m_sessionsStore.sessionForClient(sub.getClientId()); boolean targetIsActive = this.connectionDescriptors.isConnected(sub.getClientId()); - //we need to retain because duplicate only copy r/w indexes and don't retain() causing refCnt = 0 + // we need to retain because duplicate only copy r/w indexes and don't retain() causing + // refCnt = 0 ByteBuf message = origMessage.retainedDuplicate(); if (targetIsActive) { - LOG.debug("Sending PUBLISH message to active subscriber. MessageId={}, CId={}, topicFilter={}, qos={}", - pubMsg.getMessageID(), sub.getClientId(), sub.getTopicFilter(), qos); + LOG.debug( + "Sending PUBLISH message to active subscriber. MessageId={}, CId={}, topicFilter={}, qos={}", + pubMsg.getMessageID(), + sub.getClientId(), + sub.getTopicFilter(), + qos); MqttPublishMessage publishMsg = notRetainedPublish(topic, qos, message); if (qos != MqttQoS.AT_MOST_ONCE) { - //QoS 1 or 2 + // QoS 1 or 2 int messageId = targetSession.nextPacketId(); targetSession.inFlightAckWaiting(guid, messageId); - //set the PacketIdentifier only for QoS > 0 + // set the PacketIdentifier only for QoS > 0 publishMsg = notRetainedPublishWithMessageId(topic, qos, message, messageId); } this.messageSender.sendPublish(targetSession, publishMsg); } else { if (!targetSession.isCleanSession()) { - LOG.debug("Storing pending PUBLISH inactive message. MessageId={}, CId={}, topicFilter={}, qos={}", - pubMsg.getMessageID(), sub.getClientId(), sub.getTopicFilter(), qos); - //store the message in targetSession queue to deliver + LOG.debug( + "Storing pending PUBLISH inactive message. MessageId={}, CId={}, topicFilter={}, qos={}", + pubMsg.getMessageID(), + sub.getClientId(), + sub.getTopicFilter(), + qos); + // store the message in targetSession queue to deliver targetSession.enqueue(pubMsg); } } diff --git a/broker/src/main/java/io/moquette/spi/impl/PersistentQueueMessageSender.java b/broker/src/main/java/io/moquette/spi/impl/PersistentQueueMessageSender.java index bb27e27d..3dbef971 100644 --- a/broker/src/main/java/io/moquette/spi/impl/PersistentQueueMessageSender.java +++ b/broker/src/main/java/io/moquette/spi/impl/PersistentQueueMessageSender.java @@ -1,3 +1,4 @@ + package io.moquette.spi.impl; import io.moquette.server.ConnectionDescriptorStore; @@ -6,7 +7,6 @@ import io.netty.handler.codec.mqtt.MqttPublishMessage; import io.netty.handler.codec.mqtt.MqttQoS; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import static io.moquette.spi.impl.ProtocolProcessor.asStoredMessage; import static io.netty.handler.codec.mqtt.MqttQoS.AT_MOST_ONCE; @@ -21,27 +21,41 @@ class PersistentQueueMessageSender { void sendPublish(ClientSession clientsession, MqttPublishMessage pubMessage) { String clientId = clientsession.clientID; - final int messageId = pubMessage.variableHeader().messageId(); - final String topicName = pubMessage.variableHeader().topicName(); + final int messageId = pubMessage.variableHeader().messageId(); + final String topicName = pubMessage.variableHeader().topicName(); if (LOG.isDebugEnabled()) { - LOG.debug("Sending PUBLISH message. MessageId={}, CId={}, topic={}, qos={}, payload={}", messageId, - clientId, topicName, DebugUtils.payload2Str(pubMessage.payload())); + LOG.debug( + "Sending PUBLISH message. MessageId={}, CId={}, topic={}, qos={}, payload={}", + messageId, + clientId, + topicName, + DebugUtils.payload2Str(pubMessage.payload())); } else { - 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 = connectionDescriptorStore.sendMessage(pubMessage, messageId, clientId); - MqttQoS qos = pubMessage.fixedHeader().qosLevel(); - if (!messageDelivered && qos != AT_MOST_ONCE && !clientsession.isCleanSession()) { - LOG.warn( - "The PUBLISH message could not be delivered. It will be stored. MessageId = {}, CId={}, topic = {}, qos = {}, cleanSession = {}.", - messageId, clientId, topicName, qos, false); - clientsession.enqueue(asStoredMessage(pubMessage)); - } else { - LOG.warn( - "The PUBLISH message could not be delivered. It will be discarded. MessageId = {}, CId={}, topic = {}, qos = {}, cleanSession = {}.", - messageId, clientId, topicName, qos, true); - } + MqttQoS qos = pubMessage.fixedHeader().qosLevel(); + if (!messageDelivered && qos != AT_MOST_ONCE && !clientsession.isCleanSession()) { + LOG.warn( + "The PUBLISH message could not be delivered. It will be stored. " + + "MessageId = {}, CId={}, topic = {}, qos = {}, cleanSession = {}.", + messageId, + clientId, + topicName, + qos, + false); + clientsession.enqueue(asStoredMessage(pubMessage)); + } else { + LOG.warn( + "The PUBLISH message could not be delivered. It will be discarded. " + + "MessageId = {}, CId={}, topic = {}, qos = {}, cleanSession = {}.", + messageId, + clientId, + topicName, + qos, + true); + } } } diff --git a/broker/src/main/java/io/moquette/spi/impl/ProtocolProcessor.java b/broker/src/main/java/io/moquette/spi/impl/ProtocolProcessor.java index 38a17028..5f020e4b 100644 --- a/broker/src/main/java/io/moquette/spi/impl/ProtocolProcessor.java +++ b/broker/src/main/java/io/moquette/spi/impl/ProtocolProcessor.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl; import io.moquette.interception.InterceptHandler; @@ -34,7 +35,6 @@ import io.netty.handler.codec.mqtt.*; import io.netty.handler.timeout.IdleStateHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collection; @@ -43,7 +43,6 @@ import java.util.UUID; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; - import static io.moquette.spi.impl.InternalRepublisher.createPublishForQos; import static io.moquette.spi.impl.Utils.messageId; import static io.moquette.spi.impl.Utils.readBytesAndRewind; @@ -52,8 +51,8 @@ import static io.netty.handler.codec.mqtt.MqttMessageIdVariableHeader.from; import static io.netty.handler.codec.mqtt.MqttQoS.*; /** - * Class responsible to handle the logic of MQTT protocol it's the director of - * the protocol execution. + * Class responsible to handle the logic of MQTT protocol it's the director of the protocol + * execution. * * Used by the front facing class ProtocolProcessorBootstrapper. * @@ -62,6 +61,7 @@ import static io.netty.handler.codec.mqtt.MqttQoS.*; public class ProtocolProcessor { static final class WillMessage { + private final String topic; private final ByteBuffer payload; private final boolean retained; @@ -89,7 +89,6 @@ public class ProtocolProcessor { public MqttQoS getQos() { return qos; } - } private enum SubscriptionState { @@ -97,6 +96,7 @@ public class ProtocolProcessor { } private class RunningSubscription { + final String clientID; final long packetId; @@ -107,13 +107,15 @@ public class ProtocolProcessor { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; RunningSubscription that = (RunningSubscription) o; - return packetId == that.packetId && (clientID != null ? clientID.equals(that.clientID) : that.clientID == null); - + return packetId == that.packetId + && (clientID != null ? clientID.equals(that.clientID) : that.clientID == null); } @Override @@ -145,52 +147,80 @@ public class ProtocolProcessor { private MessagesPublisher messagesPublisher; private InternalRepublisher internalRepublisher; - //maps clientID to Will testament, if specified on CONNECT + // maps clientID to Will testament, if specified on CONNECT private ConcurrentMap m_willStore = new ConcurrentHashMap<>(); - ProtocolProcessor() {} - - public void init(SubscriptionsStore subscriptions, IMessagesStore storageService, - ISessionsStore sessionsStore, - IAuthenticator authenticator, - boolean allowAnonymous, IAuthorizator authorizator, BrokerInterceptor interceptor) { - init(subscriptions,storageService,sessionsStore,authenticator,allowAnonymous, false, authorizator,interceptor,null); + ProtocolProcessor() { } - public void init(SubscriptionsStore subscriptions, IMessagesStore storageService, - ISessionsStore sessionsStore, - IAuthenticator authenticator, - boolean allowAnonymous, - boolean allowZeroByteClientId, IAuthorizator authorizator, BrokerInterceptor interceptor) { - init(subscriptions,storageService,sessionsStore,authenticator,allowAnonymous, allowZeroByteClientId, authorizator,interceptor,null); + public void init(SubscriptionsStore subscriptions, IMessagesStore storageService, ISessionsStore sessionsStore, + IAuthenticator authenticator, boolean allowAnonymous, IAuthorizator authorizator, + BrokerInterceptor interceptor) { + init( + subscriptions, + storageService, + sessionsStore, + authenticator, + allowAnonymous, + false, + authorizator, + interceptor, + null); + } + + public void init(SubscriptionsStore subscriptions, IMessagesStore storageService, ISessionsStore sessionsStore, + IAuthenticator authenticator, boolean allowAnonymous, boolean allowZeroByteClientId, + IAuthorizator authorizator, BrokerInterceptor interceptor) { + init( + subscriptions, + storageService, + sessionsStore, + authenticator, + allowAnonymous, + allowZeroByteClientId, + authorizator, + interceptor, + null); + } + + public void init(SubscriptionsStore subscriptions, IMessagesStore storageService, ISessionsStore sessionsStore, + IAuthenticator authenticator, boolean allowAnonymous, boolean allowZeroByteClientId, + IAuthorizator authorizator, BrokerInterceptor interceptor, String serverPort) { + init( + new ConnectionDescriptorStore(sessionsStore), + subscriptions, + storageService, + sessionsStore, + authenticator, + allowAnonymous, + allowZeroByteClientId, + authorizator, + interceptor, + serverPort); } - - public void init(SubscriptionsStore subscriptions, IMessagesStore storageService, - ISessionsStore sessionsStore, - IAuthenticator authenticator, - boolean allowAnonymous, - boolean allowZeroByteClientId, IAuthorizator authorizator, BrokerInterceptor interceptor, String serverPort) { - init(new ConnectionDescriptorStore(sessionsStore), subscriptions, storageService, sessionsStore, authenticator, - allowAnonymous, allowZeroByteClientId, authorizator, interceptor, serverPort); - } /** - * @param subscriptions the subscription store where are stored all the existing - * clients subscriptions. - * @param storageService the persistent store to use for save/load of messages - * for QoS1 and QoS2 handling. - * @param sessionsStore the clients sessions store, used to persist subscriptions. - * @param authenticator the authenticator used in connect messages. - * @param allowAnonymous true connection to clients without credentials. - * @param allowZeroByteClientId true to allow clients connect without a clientid - * @param authorizator used to apply ACL policies to publishes and subscriptions. - * @param interceptor to notify events to an intercept handler + * @param subscriptions + * the subscription store where are stored all the existing clients subscriptions. + * @param storageService + * the persistent store to use for save/load of messages for QoS1 and QoS2 handling. + * @param sessionsStore + * the clients sessions store, used to persist subscriptions. + * @param authenticator + * the authenticator used in connect messages. + * @param allowAnonymous + * true connection to clients without credentials. + * @param allowZeroByteClientId + * true to allow clients connect without a clientid + * @param authorizator + * used to apply ACL policies to publishes and subscriptions. + * @param interceptor + * to notify events to an intercept handler */ - void init(ConnectionDescriptorStore connectionDescriptors, SubscriptionsStore subscriptions, IMessagesStore storageService, - ISessionsStore sessionsStore, - IAuthenticator authenticator, - boolean allowAnonymous, - boolean allowZeroByteClientId, IAuthorizator authorizator, BrokerInterceptor interceptor, String serverPort) { + void init(ConnectionDescriptorStore connectionDescriptors, SubscriptionsStore subscriptions, + IMessagesStore storageService, ISessionsStore sessionsStore, IAuthenticator authenticator, + boolean allowAnonymous, boolean allowZeroByteClientId, IAuthorizator authorizator, + BrokerInterceptor interceptor, String serverPort) { LOG.info("Initializing MQTT protocol processor..."); this.connectionDescriptors = connectionDescriptors; this.subscriptionInCourse = new ConcurrentHashMap<>(); @@ -199,9 +229,9 @@ public class ProtocolProcessor { this.allowAnonymous = allowAnonymous; this.allowZeroByteClientId = allowZeroByteClientId; m_authorizator = authorizator; - if (LOG.isDebugEnabled()) { - LOG.debug("Initial subscriptions tree = {}.", subscriptions.dumpTree()); - } + if (LOG.isDebugEnabled()) { + LOG.debug("Initial subscriptions tree = {}.", subscriptions.dumpTree()); + } m_authenticator = authenticator; m_messagesStore = storageService; m_sessionsStore = sessionsStore; @@ -209,15 +239,36 @@ public class ProtocolProcessor { LOG.info("Initializing messages publisher..."); final PersistentQueueMessageSender messageSender = new PersistentQueueMessageSender(this.connectionDescriptors); - this.messagesPublisher = new MessagesPublisher(connectionDescriptors, sessionsStore, m_messagesStore, messageSender); + this.messagesPublisher = new MessagesPublisher( + connectionDescriptors, + sessionsStore, + m_messagesStore, + messageSender); LOG.info("Initializing QoS publish handlers..."); - this.qos0PublishHandler = new Qos0PublishHandler(m_authorizator, subscriptions, m_messagesStore, - m_interceptor, this.messagesPublisher); - this.qos1PublishHandler = new Qos1PublishHandler(m_authorizator, subscriptions, m_messagesStore, - m_interceptor, this.connectionDescriptors, m_server_port, this.messagesPublisher); - this.qos2PublishHandler = new Qos2PublishHandler(m_authorizator, subscriptions, m_messagesStore, - m_interceptor, this.connectionDescriptors, m_sessionsStore, m_server_port, this.messagesPublisher); + this.qos0PublishHandler = new Qos0PublishHandler( + m_authorizator, + subscriptions, + m_messagesStore, + m_interceptor, + this.messagesPublisher); + this.qos1PublishHandler = new Qos1PublishHandler( + m_authorizator, + subscriptions, + m_messagesStore, + m_interceptor, + this.connectionDescriptors, + m_server_port, + this.messagesPublisher); + this.qos2PublishHandler = new Qos2PublishHandler( + m_authorizator, + subscriptions, + m_messagesStore, + m_interceptor, + this.connectionDescriptors, + m_sessionsStore, + m_server_port, + this.messagesPublisher); LOG.info("Initializing internal republisher..."); this.internalRepublisher = new InternalRepublisher(messageSender); @@ -228,8 +279,8 @@ public class ProtocolProcessor { String clientId = payload.clientIdentifier(); LOG.info("Processing CONNECT message. CId = {}, username = {}", clientId, payload.userName()); - if (msg.variableHeader().version() != MqttVersion.MQTT_3_1.protocolLevel() && - msg.variableHeader().version() != MqttVersion.MQTT_3_1_1.protocolLevel()) { + if (msg.variableHeader().version() != MqttVersion.MQTT_3_1.protocolLevel() + && msg.variableHeader().version() != MqttVersion.MQTT_3_1_1.protocolLevel()) { MqttConnAckMessage badProto = connAck(CONNECTION_REFUSED_UNACCEPTABLE_PROTOCOL_VERSION); LOG.error("The MQTT protocol version is not valid. CId = {}", clientId); @@ -250,8 +301,10 @@ public class ProtocolProcessor { // Generating client id. clientId = UUID.randomUUID().toString().replace("-", ""); - LOG.info("The client has connected with a server generated identifier. CId = {}, username = {}", - clientId, payload.userName()); + LOG.info( + "The client has connected with a server generated identifier. CId = {}, username = {}", + clientId, + payload.userName()); } if (!login(channel, msg, clientId)) { @@ -259,11 +312,13 @@ public class ProtocolProcessor { return; } - ConnectionDescriptor descriptor = new ConnectionDescriptor(clientId, channel, msg.variableHeader().isCleanSession()); + ConnectionDescriptor descriptor = new ConnectionDescriptor( + clientId, + channel, + msg.variableHeader().isCleanSession()); ConnectionDescriptor existing = this.connectionDescriptors.addConnection(descriptor); if (existing != null) { - LOG.info("The client ID is being used in an existing connection. It will be closed. CId = {}", - clientId); + LOG.info("The client ID is being used in an existing connection. It will be closed. CId = {}", clientId); existing.abort(); return; } @@ -289,7 +344,8 @@ public class ProtocolProcessor { channel.close(); return; } - final boolean success = descriptor.assignState(ConnectionState.MESSAGES_REPUBLISHED, ConnectionState.ESTABLISHED); + final boolean success = descriptor + .assignState(ConnectionState.MESSAGES_REPUBLISHED, ConnectionState.ESTABLISHED); if (!success) { channel.close(); } @@ -306,32 +362,42 @@ public class ProtocolProcessor { } private MqttConnAckMessage connAck(MqttConnectReturnCode returnCode, boolean sessionPresent) { - MqttFixedHeader mqttFixedHeader = new MqttFixedHeader(MqttMessageType.CONNACK, false, MqttQoS.AT_MOST_ONCE, false, 0); + MqttFixedHeader mqttFixedHeader = new MqttFixedHeader( + MqttMessageType.CONNACK, + false, + MqttQoS.AT_MOST_ONCE, + false, + 0); MqttConnAckVariableHeader mqttConnAckVariableHeader = new MqttConnAckVariableHeader(returnCode, sessionPresent); return new MqttConnAckMessage(mqttFixedHeader, mqttConnAckVariableHeader); } private boolean login(Channel channel, MqttConnectMessage msg, final String clientId) { - //handle user authentication + // handle user authentication if (msg.variableHeader().hasUserName()) { byte[] pwd = null; if (msg.variableHeader().hasPassword()) { pwd = msg.payload().password().getBytes(); } else if (!this.allowAnonymous) { - LOG.error("The client didn't supply any password and MQTT anonymous mode is disabled. CId = {}.", + LOG.error( + "The client didn't supply any password and MQTT anonymous mode is disabled. CId = {}.", clientId); failedCredentials(channel); return false; } if (!m_authenticator.checkValid(clientId, msg.payload().userName(), pwd)) { - LOG.error("The authenticator has rejected the MQTT credentials. CId = {}, username = {}, password = {}.", - clientId, msg.payload().userName(), pwd); + LOG.error( + "The authenticator has rejected the MQTT credentials. CId = {}, username = {}, password = {}.", + clientId, + msg.payload().userName(), + pwd); failedCredentials(channel); return false; } NettyUtils.userName(channel, msg.payload().userName()); } else if (!this.allowAnonymous) { - LOG.error("The client didn't supply any credentials and MQTT anonymous mode is disabled. CId = {}.", + LOG.error( + "The client didn't supply any credentials and MQTT anonymous mode is disabled. CId = {}.", clientId); failedCredentials(channel); return false; @@ -340,7 +406,7 @@ public class ProtocolProcessor { } private boolean sendAck(ConnectionDescriptor descriptor, MqttConnectMessage msg, final String clientId) { - LOG.info("Sending connect ACK. CId = {}.", clientId); + LOG.info("Sending connect ACK. CId = {}.", clientId); final boolean success = descriptor.assignState(ConnectionState.DISCONNECTED, ConnectionState.SENDACK); if (!success) { return false; @@ -356,7 +422,7 @@ public class ProtocolProcessor { } if (isSessionAlreadyStored) { - LOG.info("Cleaning session. CId = {}.", clientId); + LOG.info("Cleaning session. CId = {}.", clientId); clientSession.cleanSession(msg.variableHeader().isCleanSession()); } descriptor.writeAndFlush(okResp); @@ -368,35 +434,48 @@ public class ProtocolProcessor { int keepAlive = msg.variableHeader().keepAliveTimeSeconds(); LOG.info("Configuring connection. CId = {}.", clientId); NettyUtils.keepAlive(channel, keepAlive); - //session.attr(NettyUtils.ATTR_KEY_CLEANSESSION).set(msg.variableHeader().isCleanSession()); + // session.attr(NettyUtils.ATTR_KEY_CLEANSESSION).set(msg.variableHeader().isCleanSession()); NettyUtils.cleanSession(channel, msg.variableHeader().isCleanSession()); - //used to track the client in the subscription and publishing phases. - //session.attr(NettyUtils.ATTR_KEY_CLIENTID).set(msg.getClientID()); + // used to track the client in the subscription and publishing phases. + // session.attr(NettyUtils.ATTR_KEY_CLIENTID).set(msg.getClientID()); NettyUtils.clientID(channel, clientId); int idleTime = Math.round(keepAlive * 1.5f); setIdleTime(channel.pipeline(), idleTime); - LOG.info("The connection has been configured. CId = {}, keepAlive = {}, cleanSession = {}, idleTime = {}.", - clientId, keepAlive, msg.variableHeader().isCleanSession(), idleTime); + LOG.info( + "The connection has been configured. CId = {}, keepAlive = {}, cleanSession = {}, idleTime = {}.", + clientId, + keepAlive, + msg.variableHeader().isCleanSession(), + idleTime); } private void storeWillMessage(MqttConnectMessage msg, final String clientId) { - //Handle will flag + // Handle will flag if (msg.variableHeader().isWillFlag()) { MqttQoS willQos = MqttQoS.valueOf(msg.variableHeader().willQos()); - LOG.info("Configuring MQTT last will and testament. CId = {}, willQos = {}, willTopic = {}, willRetain = {}.", - clientId, willQos, msg.payload().willTopic(), msg.variableHeader().isWillRetain()); + LOG.info( + "Configuring MQTT last will and testament. " + + "CId = {}, willQos = {}, willTopic = {}, willRetain = {}.", + clientId, + willQos, + msg.payload().willTopic(), + msg.variableHeader().isWillRetain()); byte[] willPayload = msg.payload().willMessage().getBytes(); ByteBuffer bb = (ByteBuffer) ByteBuffer.allocate(willPayload.length).put(willPayload).flip(); - //save the will testament in the clientID store - WillMessage will = new WillMessage(msg.payload().willTopic(), bb, msg.variableHeader().isWillRetain(), willQos); + // save the will testament in the clientID store + WillMessage will = new WillMessage( + msg.payload().willTopic(), + bb, + msg.variableHeader().isWillRetain(), + willQos); m_willStore.put(clientId, will); LOG.info("MQTT last will and testament has been configured. CId = {}.", clientId); } } private ClientSession createOrLoadClientSession(ConnectionDescriptor descriptor, MqttConnectMessage msg, - String clientId) { + String clientId) { final boolean success = descriptor.assignState(ConnectionState.SENDACK, ConnectionState.SESSION_CREATED); if (!success) { return null; @@ -408,23 +487,24 @@ public class ProtocolProcessor { clientSession = m_sessionsStore.createNewSession(clientId, msg.variableHeader().isCleanSession()); } if (msg.variableHeader().isCleanSession()) { - LOG.info("Cleaning session. CId = {}.", clientId); + LOG.info("Cleaning session. CId = {}.", clientId); clientSession.cleanSession(); } return clientSession; } private boolean republish(ConnectionDescriptor descriptor, MqttConnectMessage msg, ClientSession clientSession) { - final boolean success = descriptor.assignState(ConnectionState.SESSION_CREATED, ConnectionState.MESSAGES_REPUBLISHED); + final boolean success = descriptor + .assignState(ConnectionState.SESSION_CREATED, ConnectionState.MESSAGES_REPUBLISHED); if (!success) { return false; } if (!msg.variableHeader().isCleanSession()) { - //force the republish of stored QoS1 and QoS2 + // force the republish of stored QoS1 and QoS2 republishStoredInSession(clientSession); } - int flushIntervalMs = 500/*(keepAlive * 1000) / 2*/; + int flushIntervalMs = 500/* (keepAlive * 1000) / 2 */; descriptor.setupAutoFlusher(flushIntervalMs); return true; } @@ -443,7 +523,7 @@ public class ProtocolProcessor { /** * Republish QoS1 and QoS2 messages stored into the session for the clientID. - * */ + */ private void republishStoredInSession(ClientSession clientSession) { LOG.info("Republishing stored publish events. CId = {}.", clientSession.clientID); BlockingQueue publishedEvents = clientSession.queue(); @@ -470,19 +550,24 @@ public class ProtocolProcessor { } public static IMessagesStore.StoredMessage asStoredMessage(MqttPublishMessage msg) { - //TODO ugly, too much array copy + // TODO ugly, too much array copy ByteBuf payload = msg.payload(); byte[] payloadContent = readBytesAndRewind(payload); - IMessagesStore.StoredMessage stored = new IMessagesStore.StoredMessage(payloadContent, - msg.fixedHeader().qosLevel(), msg.variableHeader().topicName()); + IMessagesStore.StoredMessage stored = new IMessagesStore.StoredMessage( + payloadContent, + msg.fixedHeader().qosLevel(), + msg.variableHeader().topicName()); stored.setRetained(msg.fixedHeader().isRetain()); stored.setMessageID(msg.variableHeader().messageId()); return stored; } private static IMessagesStore.StoredMessage asStoredMessage(WillMessage will) { - IMessagesStore.StoredMessage pub = new IMessagesStore.StoredMessage(will.getPayload().array(), will.getQos(), will.getTopic()); + IMessagesStore.StoredMessage pub = new IMessagesStore.StoredMessage( + will.getPayload().array(), + will.getQos(), + will.getTopic()); pub.setRetained(will.isRetained()); return pub; } @@ -490,8 +575,12 @@ public class ProtocolProcessor { public void processPublish(Channel channel, MqttPublishMessage msg) { final MqttQoS qos = msg.fixedHeader().qosLevel(); final String clientId = NettyUtils.clientID(channel); - LOG.info("Processing PUBLISH message. CId = {}, topic = {}, messageId = {}, qos = {}.", - clientId, msg.variableHeader().topicName(), msg.variableHeader().messageId(), qos); + LOG.info( + "Processing PUBLISH message. CId = {}, topic = {}, messageId = {}, qos = {}.", + clientId, + msg.variableHeader().topicName(), + msg.variableHeader().messageId(), + qos); switch (qos) { case AT_MOST_ONCE: this.qos0PublishHandler.receivedPublishQos0(channel, msg); @@ -503,21 +592,22 @@ public class ProtocolProcessor { this.qos2PublishHandler.receivedPublishQos2(channel, msg); break; default: - break; + break; } } /** - * Intended usage is only for embedded versions of the broker, where the hosting application want to use the - * broker to send a publish message. - * Inspired by {@link #processPublish} but with some changes to avoid security check, and the handshake phases - * for Qos1 and Qos2. - * It also doesn't notifyTopicPublished because using internally the owner should already know where - * it's publishing. + * Intended usage is only for embedded versions of the broker, where the hosting application + * want to use the broker to send a publish message. Inspired by {@link #processPublish} but + * with some changes to avoid security check, and the handshake phases for Qos1 and Qos2. It + * also doesn't notifyTopicPublished because using internally the owner should already know + * where it's publishing. * - * @param msg the message to publish. - * @param clientId the clientID - * */ + * @param msg + * the message to publish. + * @param clientId + * the clientID + */ public void internalPublish(MqttPublishMessage msg, final String clientId) { final MqttQoS qos = msg.fixedHeader().qosLevel(); final String topic = msg.variableHeader().topicName(); @@ -531,7 +621,7 @@ public class ProtocolProcessor { toStoreMsg.setClientID(clientId); } toStoreMsg.setMessageID(1); - if (qos == EXACTLY_ONCE) { //QoS2 + if (qos == EXACTLY_ONCE) { // QoS2 guid = m_messagesStore.storePublishForFuture(toStoreMsg); } List topicMatchingSubscriptions = subscriptions.matches(topic); @@ -541,12 +631,12 @@ public class ProtocolProcessor { return; } if (qos == AT_MOST_ONCE || msg.payload().readableBytes() == 0) { - //QoS == 0 && retain => clean old retained + // QoS == 0 && retain => clean old retained m_messagesStore.cleanRetained(topic); return; } if (guid == null) { - //before wasn't stored + // before wasn't stored guid = m_messagesStore.storePublishForFuture(toStoreMsg); } m_messagesStore.storeRetained(topic, guid); @@ -556,8 +646,8 @@ public class ProtocolProcessor { * Specialized version to publish will testament message. */ private void forwardPublishWill(WillMessage will, String clientID) { - //it has just to publish the message downstream to the subscribers - //NB it's a will publish, it needs a PacketIdentifier for this conn, default to 1 + // it has just to publish the message downstream to the subscribers + // NB it's a will publish, it needs a PacketIdentifier for this conn, default to 1 Integer messageId = null; if (will.getQos() != AT_MOST_ONCE) { messageId = m_sessionsStore.nextPacketID(clientID); @@ -569,7 +659,7 @@ public class ProtocolProcessor { String topic = tobeStored.getTopic(); List topicMatchingSubscriptions = subscriptions.matches(topic); - LOG.info("Publishing will message. CId = {}, messageId = {}, topic = {}.", clientID, messageId, topic); + LOG.info("Publishing will message. CId = {}, messageId = {}, topic = {}.", clientID, messageId, topic); this.messagesPublisher.publish2Subscribers(tobeStored, topicMatchingSubscriptions); } @@ -581,11 +671,14 @@ public class ProtocolProcessor { } /** - * Second phase of a publish QoS2 protocol, sent by publisher to the broker. Search the stored message and publish - * to all interested subscribers. - * @param channel the channel of the incoming message. - * @param msg the decoded pubrel message. - * */ + * Second phase of a publish QoS2 protocol, sent by publisher to the broker. Search the stored + * message and publish to all interested subscribers. + * + * @param channel + * the channel of the incoming message. + * @param msg + * the decoded pubrel message. + */ public void processPubRel(Channel channel, MqttMessage msg) { this.qos2PublishHandler.processPubRel(channel, msg); } @@ -593,10 +686,10 @@ public class ProtocolProcessor { public void processPubRec(Channel channel, MqttMessage msg) { String clientID = NettyUtils.clientID(channel); ClientSession targetSession = m_sessionsStore.sessionForClient(clientID); - //remove from the inflight and move to the QoS2 second phase queue + // remove from the inflight and move to the QoS2 second phase queue int messageID = messageId(msg); targetSession.moveInFlightToSecondPhaseAckWaiting(messageID); - //once received a PUBREC reply with a PUBREL(messageID) + // once received a PUBREC reply with a PUBREL(messageID) LOG.debug("Processing PUBREC message. CId = {}, messageId = {}.", clientID, messageID); MqttFixedHeader pubRelHeader = new MqttFixedHeader(MqttMessageType.PUBREL, false, AT_LEAST_ONCE, false, 0); @@ -608,7 +701,7 @@ public class ProtocolProcessor { String clientID = NettyUtils.clientID(channel); int messageID = messageId(msg); LOG.debug("Processing PUBCOMP message. CId = {}, messageId = {}.", clientID, messageID); - //once received the PUBCOMP then remove the message from the temp memory + // once received the PUBCOMP then remove the message from the temp memory ClientSession targetSession = m_sessionsStore.sessionForClient(clientID); StoredMessage inflightMsg = targetSession.secondPhaseAcknowledged(messageID); String username = NettyUtils.userName(channel); @@ -617,59 +710,59 @@ public class ProtocolProcessor { } public void processDisconnect(Channel channel) throws InterruptedException { - final String clientID = NettyUtils.clientID(channel); - LOG.info("Processing DISCONNECT message. CId = {}.", clientID); - channel.flush(); + final String clientID = NettyUtils.clientID(channel); + LOG.info("Processing DISCONNECT message. CId = {}.", clientID); + channel.flush(); final ConnectionDescriptor existingDescriptor = this.connectionDescriptors.getConnection(clientID); if (existingDescriptor == null) { - //another client with same ID removed the descriptor, we must exit + // another client with same ID removed the descriptor, we must exit channel.close(); return; } if (existingDescriptor.doesNotUseChannel(channel)) { - //another client saved it's descriptor, exit - LOG.warn("Another client is using the connection descriptor. Closing connection. CId = {}.", - clientID); - existingDescriptor.abort(); + // another client saved it's descriptor, exit + LOG.warn("Another client is using the connection descriptor. Closing connection. CId = {}.", clientID); + existingDescriptor.abort(); return; } if (!removeSubscriptions(existingDescriptor, clientID)) { - LOG.warn("Unable to remove subscriptions. Closing connection. CId = {}.", clientID); - existingDescriptor.abort(); + LOG.warn("Unable to remove subscriptions. Closing connection. CId = {}.", clientID); + existingDescriptor.abort(); return; } if (!dropStoredMessages(existingDescriptor, clientID)) { - LOG.warn("Unable to drop stored messages. Closing connection. CId = {}.", clientID); - existingDescriptor.abort(); + LOG.warn("Unable to drop stored messages. Closing connection. CId = {}.", clientID); + existingDescriptor.abort(); return; } if (!cleanWillMessageAndNotifyInterceptor(existingDescriptor, clientID)) { - LOG.warn("Unable to drop will message. Closing connection. CId = {}.", clientID); - existingDescriptor.abort(); + LOG.warn("Unable to drop will message. Closing connection. CId = {}.", clientID); + existingDescriptor.abort(); return; } if (!existingDescriptor.close()) { - LOG.info("The connection has been closed. CId = {}.", clientID); + LOG.info("The connection has been closed. CId = {}.", clientID); return; } boolean stillPresent = this.connectionDescriptors.removeConnection(existingDescriptor); if (!stillPresent) { - //another descriptor was inserted - LOG.warn("Another descriptor has been inserted. CId = {}.", clientID); - return; + // another descriptor was inserted + LOG.warn("Another descriptor has been inserted. CId = {}.", clientID); + return; } - LOG.info("The DISCONNECT message has been processed. CId = {}.", clientID); + LOG.info("The DISCONNECT message has been processed. CId = {}.", clientID); } private boolean removeSubscriptions(ConnectionDescriptor descriptor, String clientID) { - final boolean success = descriptor.assignState(ConnectionState.ESTABLISHED, ConnectionState.SUBSCRIPTIONS_REMOVED); + final boolean success = descriptor + .assignState(ConnectionState.ESTABLISHED, ConnectionState.SUBSCRIPTIONS_REMOVED); if (!success) { return false; } @@ -683,7 +776,8 @@ public class ProtocolProcessor { } private boolean dropStoredMessages(ConnectionDescriptor descriptor, String clientID) { - final boolean success = descriptor.assignState(ConnectionState.SUBSCRIPTIONS_REMOVED, ConnectionState.MESSAGES_DROPPED); + final boolean success = descriptor + .assignState(ConnectionState.SUBSCRIPTIONS_REMOVED, ConnectionState.MESSAGES_DROPPED); if (!success) { return false; } @@ -697,13 +791,14 @@ public class ProtocolProcessor { } private boolean cleanWillMessageAndNotifyInterceptor(ConnectionDescriptor descriptor, String clientID) { - final boolean success = descriptor.assignState(ConnectionState.MESSAGES_DROPPED, ConnectionState.INTERCEPTORS_NOTIFIED); + final boolean success = descriptor + .assignState(ConnectionState.MESSAGES_DROPPED, ConnectionState.INTERCEPTORS_NOTIFIED); if (!success) { return false; } LOG.info("Removing will message. ClientId = {}.", descriptor.clientID); - //cleanup the will store + // cleanup the will store m_willStore.remove(clientID); String username = descriptor.getUsername(); m_interceptor.notifyClientDisconnected(clientID, username); @@ -711,10 +806,10 @@ public class ProtocolProcessor { } public void processConnectionLost(String clientID, Channel channel) { - LOG.info("Processing connection lost event. CId = {}.", clientID); + LOG.info("Processing connection lost event. CId = {}.", clientID); ConnectionDescriptor oldConnDescr = new ConnectionDescriptor(clientID, channel, true); connectionDescriptors.removeConnection(oldConnDescr); - //publish the Will message (if any) for the clientID + // publish the Will message (if any) for the clientID if (m_willStore.containsKey(clientID)) { WillMessage will = m_willStore.get(clientID); forwardPublishWill(will, clientID); @@ -726,25 +821,31 @@ public class ProtocolProcessor { } /** - * Remove the clientID from topic subscription, if not previously subscribed, - * doesn't reply any error. - * @param channel the channel of the incoming message. - * @param msg the decoded unsubscribe message. + * Remove the clientID from topic subscription, if not previously subscribed, doesn't reply any + * error. + * + * @param channel + * the channel of the incoming message. + * @param msg + * the decoded unsubscribe message. */ public void processUnsubscribe(Channel channel, MqttUnsubscribeMessage msg) { List topics = msg.payload().topics(); String clientID = NettyUtils.clientID(channel); - LOG.info("Processing UNSUBSCRIBE message. CId = {}, topics = {}.", clientID, topics); + LOG.info("Processing UNSUBSCRIBE message. CId = {}, topics = {}.", clientID, topics); ClientSession clientSession = m_sessionsStore.sessionForClient(clientID); for (String topic : topics) { boolean validTopic = SubscriptionsStore.validate(topic); if (!validTopic) { - //close the connection, not valid topicFilter is a protocol violation + // close the connection, not valid topicFilter is a protocol violation channel.close(); - LOG.error("The topic filter is not valid. CId = {}, topics = {}, badTopicFilter = {}.", - clientID, topics, topic); + LOG.error( + "The topic filter is not valid. CId = {}, topics = {}, badTopicFilter = {}.", + clientID, + topics, + topic); return; } @@ -755,57 +856,64 @@ public class ProtocolProcessor { m_interceptor.notifyTopicUnsubscribed(topic, clientID, username); } - //ack the client + // ack the client int messageID = msg.variableHeader().messageId(); MqttFixedHeader fixedHeader = new MqttFixedHeader(MqttMessageType.UNSUBACK, false, AT_LEAST_ONCE, false, 0); MqttUnsubAckMessage ackMessage = new MqttUnsubAckMessage(fixedHeader, from(messageID)); - LOG.info("Sending UNSUBACK message. CId = {}, topics = {}, messageId = {}.", clientID, topics, messageID); + LOG.info("Sending UNSUBACK message. CId = {}, topics = {}, messageId = {}.", clientID, topics, messageID); channel.writeAndFlush(ackMessage); } public void processSubscribe(Channel channel, MqttSubscribeMessage msg) { String clientID = NettyUtils.clientID(channel); int messageID = messageId(msg); - LOG.info("Processing SUBSCRIBE message. CId = {}, messageId = {}.", clientID, messageID); + LOG.info("Processing SUBSCRIBE message. CId = {}, messageId = {}.", clientID, messageID); RunningSubscription executionKey = new RunningSubscription(clientID, messageID); - SubscriptionState currentStatus = this.subscriptionInCourse.putIfAbsent(executionKey, SubscriptionState.VERIFIED); + SubscriptionState currentStatus = this.subscriptionInCourse + .putIfAbsent(executionKey, SubscriptionState.VERIFIED); if (currentStatus != null) { - LOG.warn("The client sent another SUBSCRIBE message while this one was being processed. " + - "CId = {}, messageId = {}.", clientID, messageID); + LOG.warn( + "The client sent another SUBSCRIBE message while this one was being processed. " + + "CId = {}, messageId = {}.", + clientID, + messageID); return; } String username = NettyUtils.userName(channel); List ackTopics = doVerify(clientID, username, msg); MqttSubAckMessage ackMessage = doAckMessageFromValidateFilters(ackTopics, messageID); if (!this.subscriptionInCourse.replace(executionKey, SubscriptionState.VERIFIED, SubscriptionState.STORED)) { - LOG.warn("The client sent another SUBSCRIBE message while the topic filters were being verified. " + - "CId = {}, messageId = {}.", clientID, messageID); + LOG.warn( + "The client sent another SUBSCRIBE message while the topic filters were being verified. " + + "CId = {}, messageId = {}.", + clientID, + messageID); return; } - LOG.info("Creating and storing subscriptions CId={}, messageId={}, topics={}", clientID, messageID, ackTopics); + LOG.info("Creating and storing subscriptions CId={}, messageId={}, topics={}", clientID, messageID, ackTopics); List newSubscriptions = doStoreSubscription(ackTopics, clientID); - //save session, persist subscriptions from session + // save session, persist subscriptions from session for (Subscription subscription : newSubscriptions) { subscriptions.add(subscription.asClientTopicCouple()); } - LOG.info("Sending SUBACK response CId={}, messageId={}", clientID, messageID); + LOG.info("Sending SUBACK response CId={}, messageId={}", clientID, messageID); channel.writeAndFlush(ackMessage); - //fire the persisted messages in session + // fire the persisted messages in session for (Subscription subscription : newSubscriptions) { publishRetainedMessagesInSession(subscription, username); } boolean success = this.subscriptionInCourse.remove(executionKey, SubscriptionState.STORED); if (!success) { - LOG.warn("Unable to perform the final subscription state update CId={}, messageId={}", clientID, messageID); + LOG.warn("Unable to perform the final subscription state update CId={}, messageId={}", clientID, messageID); } } @@ -814,7 +922,7 @@ public class ProtocolProcessor { List newSubscriptions = new ArrayList<>(); for (MqttTopicSubscription req : ackTopics) { - //TODO this is SUPER UGLY + // TODO this is SUPER UGLY if (req.qualityOfService() == FAILURE) { continue; } @@ -826,11 +934,14 @@ public class ProtocolProcessor { } /** - * @param clientID the clientID - * @param username the username - * @param msg the subscribe message to verify + * @param clientID + * the clientID + * @param username + * the username + * @param msg + * the subscribe message to verify * @return the list of verified topics for the given subscribe message. - * */ + */ private List doVerify(String clientID, String username, MqttSubscribeMessage msg) { ClientSession clientSession = m_sessionsStore.sessionForClient(clientID); List ackTopics = new ArrayList<>(); @@ -838,20 +949,34 @@ public class ProtocolProcessor { final int messageId = messageId(msg); for (MqttTopicSubscription req : msg.payload().topicSubscriptions()) { if (!m_authorizator.canRead(req.topicName(), username, clientSession.clientID)) { - //send SUBACK with 0x80, the user hasn't credentials to read the topic - LOG.error("The client does not have read permissions on the topic. CId = {}, username = {}, messageId = {}, topic = {}.", - clientID, username, messageId, req.topicName()); + // send SUBACK with 0x80, the user hasn't credentials to read the topic + LOG.error( + "The client does not have read permissions on the topic. " + + "CId = {}, username = {}, messageId = {}, topic = {}.", + clientID, + username, + messageId, + req.topicName()); ackTopics.add(new MqttTopicSubscription(req.topicName(), FAILURE)); } else { MqttQoS qos; if (SubscriptionsStore.validate(req.topicName())) { - LOG.info("The client will be subscribed to the topic. CId = {}, username = {}, messageId = {}, topic = {}.", - clientID, username, messageId, req.topicName()); + LOG.info( + "The client will be subscribed to the topic. " + + "CId = {}, username = {}, messageId = {}, topic = {}.", + clientID, + username, + messageId, + req.topicName()); qos = req.qualityOfService(); } else { - LOG.error("The topic filter is not valid. CId = {}, username = {}, messageId = {}, topic = {}.", - clientID, username, messageId, req.topicName()); - qos = FAILURE; + LOG.error( + "The topic filter is not valid. CId = {}, username = {}, messageId = {}, topic = {}.", + clientID, + username, + messageId, + req.topicName()); + qos = FAILURE; } ackTopics.add(new MqttTopicSubscription(req.topicName(), qos)); } @@ -861,7 +986,7 @@ public class ProtocolProcessor { /** * Create the SUBACK response from a list of topicFilters - * */ + */ private MqttSubAckMessage doAckMessageFromValidateFilters(List topicFilters, int messageId) { List grantedQoSLevels = new ArrayList<>(); for (MqttTopicSubscription req : topicFilters) { @@ -874,12 +999,15 @@ public class ProtocolProcessor { } private void publishRetainedMessagesInSession(final Subscription newSubscription, String username) { - LOG.info("Retrieving retained messages. CId = {}, topics = {}.", newSubscription.getClientId(), - newSubscription.getTopicFilter()); + LOG.info( + "Retrieving retained messages. CId = {}, topics = {}.", + newSubscription.getClientId(), + newSubscription.getTopicFilter()); - //scans retained messages to be published to the new subscription - //TODO this is ugly, it does a linear scan on potential big dataset + // scans retained messages to be published to the new subscription + // TODO this is ugly, it does a linear scan on potential big dataset Collection messages = m_messagesStore.searchMatching(new IMatchingCondition() { + @Override public boolean match(String key) { return SubscriptionsStore.matchTopics(key, newSubscription.getTopicFilter()); @@ -887,13 +1015,16 @@ public class ProtocolProcessor { }); if (!messages.isEmpty()) { - LOG.info("Publishing retained messages. CId = {}, topics = {}, messagesNo = {}.", - newSubscription.getClientId(), newSubscription.getTopicFilter(), messages.size()); + LOG.info( + "Publishing retained messages. CId = {}, topics = {}, messagesNo = {}.", + newSubscription.getClientId(), + newSubscription.getTopicFilter(), + messages.size()); } ClientSession targetSession = m_sessionsStore.sessionForClient(newSubscription.getClientId()); this.internalRepublisher.publishRetained(targetSession, messages); - //notify the Observables + // notify the Observables m_interceptor.notifyTopicSubscribed(newSubscription, username); } @@ -901,14 +1032,19 @@ public class ProtocolProcessor { String clientID = NettyUtils.clientID(channel); ClientSession clientSession = m_sessionsStore.sessionForClient(clientID); boolean emptyQueue = false; - while (channel.isWritable() && !emptyQueue) { + while (channel.isWritable() && !emptyQueue) { StoredMessage msg = clientSession.queue().poll(); if (msg == null) { emptyQueue = true; } else { - //recreate a publish from stored publish in queue + // recreate a publish from stored publish in queue boolean retained = m_messagesStore.getMessageByGuid(msg.getGuid()) != null; - MqttPublishMessage pubMsg = createPublishForQos(msg.getTopic(), msg.getQos(), msg.getMessage(), retained, 0); + MqttPublishMessage pubMsg = createPublishForQos( + msg.getTopic(), + msg.getQos(), + msg.getMessage(), + retained, + 0); channel.write(pubMsg); } } diff --git a/broker/src/main/java/io/moquette/spi/impl/ProtocolProcessorBootstrapper.java b/broker/src/main/java/io/moquette/spi/impl/ProtocolProcessorBootstrapper.java index e2dfeb11..b98135ff 100644 --- a/broker/src/main/java/io/moquette/spi/impl/ProtocolProcessorBootstrapper.java +++ b/broker/src/main/java/io/moquette/spi/impl/ProtocolProcessorBootstrapper.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl; import io.moquette.BrokerConstants; @@ -35,7 +36,6 @@ import io.moquette.spi.security.IAuthenticator; import io.moquette.spi.security.IAuthorizator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.text.ParseException; @@ -54,13 +54,13 @@ public class ProtocolProcessorBootstrapper { private SubscriptionsStore subscriptions; private MapDBPersistentStore m_mapStorage; - + private ISessionsStore m_sessionsStore; private BrokerInterceptor m_interceptor; private final ProtocolProcessor m_processor = new ProtocolProcessor(); - + private ConnectionDescriptorStore connectionDescriptors; public ProtocolProcessorBootstrapper() { @@ -68,19 +68,25 @@ public class ProtocolProcessorBootstrapper { /** * Initialize the processing part of the broker. - * @param props the properties carrier where some props like port end host could be loaded. - * For the full list check of configurable properties check moquette.conf file. - * @param embeddedObservers a list of callbacks to be notified of certain events inside the broker. - * Could be empty list of null. - * @param authenticator an implementation of the authenticator to be used, if null load that specified in config - * and fallback on the default one (permit all). - * @param authorizator an implementation of the authorizator to be used, if null load that specified in config - * and fallback on the default one (permit all). - * @param server the serber to init. + * + * @param props + * the properties carrier where some props like port end host could be loaded. For + * the full list check of configurable properties check moquette.conf file. + * @param embeddedObservers + * a list of callbacks to be notified of certain events inside the broker. Could be + * empty list of null. + * @param authenticator + * an implementation of the authenticator to be used, if null load that specified in + * config and fallback on the default one (permit all). + * @param authorizator + * an implementation of the authorizator to be used, if null load that specified in + * config and fallback on the default one (permit all). + * @param server + * the serber to init. * @return the processor created for the broker. - * */ + */ public ProtocolProcessor init(IConfig props, List embeddedObservers, - IAuthenticator authenticator, IAuthorizator authorizator, Server server) { + IAuthenticator authenticator, IAuthorizator authorizator, Server server) { subscriptions = new SubscriptionsStore(); LOG.info("Initializing messages and sessions stores..."); @@ -94,10 +100,10 @@ public class ProtocolProcessorBootstrapper { List observers = new ArrayList<>(embeddedObservers); String interceptorClassName = props.getProperty(BrokerConstants.INTERCEPT_HANDLER_PROPERTY_NAME); if (interceptorClassName != null && !interceptorClassName.isEmpty()) { - InterceptHandler handler = loadClass(interceptorClassName, InterceptHandler.class, Server.class, server); - if (handler != null) { - observers.add(handler); - } + InterceptHandler handler = loadClass(interceptorClassName, InterceptHandler.class, Server.class, server); + if (handler != null) { + observers.add(handler); + } } m_interceptor = new BrokerInterceptor(props, observers); @@ -136,82 +142,121 @@ public class ProtocolProcessorBootstrapper { LOG.info("Parsing ACL file. Path = {}.", aclFilePath); authorizator = ACLFileParser.parse(resourceLoader.loadResource(aclFilePath)); } catch (ParseException pex) { - LOG.error("Unable to parse ACL file. Path = {}, cause = {}, errorMessage = {}.", aclFilePath, - pex.getCause(), pex.getMessage()); + LOG.error( + "Unable to parse ACL file. Path = {}, cause = {}, errorMessage = {}.", + aclFilePath, + pex.getCause(), + pex.getMessage()); } } else { authorizator = new PermitAllAuthorizator(); } LOG.info("An {} authorizator instance will be used.", authorizator.getClass().getName()); } - + LOG.info("Initializing connection descriptor store..."); connectionDescriptors = new ConnectionDescriptorStore(m_sessionsStore); LOG.info("Initializing MQTT protocol processor..."); - boolean allowAnonymous = Boolean.parseBoolean(props.getProperty(BrokerConstants.ALLOW_ANONYMOUS_PROPERTY_NAME, "true")); - boolean allowZeroByteClientId = Boolean.parseBoolean(props.getProperty(BrokerConstants.ALLOW_ZERO_BYTE_CLIENT_ID_PROPERTY_NAME, "false")); - m_processor.init(connectionDescriptors, subscriptions, messagesStore, m_sessionsStore, authenticator, allowAnonymous, allowZeroByteClientId, authorizator, m_interceptor, props.getProperty(BrokerConstants.PORT_PROPERTY_NAME)); + boolean allowAnonymous = Boolean + .parseBoolean(props.getProperty(BrokerConstants.ALLOW_ANONYMOUS_PROPERTY_NAME, "true")); + boolean allowZeroByteClientId = Boolean + .parseBoolean(props.getProperty(BrokerConstants.ALLOW_ZERO_BYTE_CLIENT_ID_PROPERTY_NAME, "false")); + m_processor.init( + connectionDescriptors, + subscriptions, + messagesStore, + m_sessionsStore, + authenticator, + allowAnonymous, + allowZeroByteClientId, + authorizator, + m_interceptor, + props.getProperty(BrokerConstants.PORT_PROPERTY_NAME)); return m_processor; } - - @SuppressWarnings("unchecked") - private T loadClass(String className, Class iface, Class constructorArgClass, U props) { - T instance = null; - try { - LOG.info("Loading class. ClassName = {}, interfaceName = {}.", className, iface.getName()); - Class clazz = Class.forName(className); - // check if method getInstance exists - Method method = clazz.getMethod("getInstance", new Class[] {}); - try { - LOG.info("Invoking getInstance() method. ClassName = {}, interfaceName = {}.", className, - iface.getName()); - instance = (T) method.invoke(null, new Object[] {}); - } catch (IllegalArgumentException | InvocationTargetException | IllegalAccessException ex) { - LOG.error( - "Unable to invoke getInstance() method. ClassName = {}, interfaceName = {}, cause = {}, errorMessage = {}.", - className, iface.getName(), ex.getCause(), ex.getMessage()); - return null; - } - } catch (NoSuchMethodException nsmex) { - try { - // check if constructor with constructor arg class parameter - // exists - LOG.info("Invoking constructor with {} argument. ClassName = {}, interfaceName = {}.", - constructorArgClass.getName(), className, iface.getName()); - instance = this.getClass().getClassLoader().loadClass(className).asSubclass(iface) - .getConstructor(constructorArgClass).newInstance(props); - } catch (InstantiationException | IllegalAccessException | ClassNotFoundException ex) { - LOG.warn( - "Unable to invoke constructor with {} argument. ClassName = {}, interfaceName = {}, cause = {}, errorMessage = {}.", - constructorArgClass.getName(), className, iface.getName(), ex.getCause(), ex.getMessage()); - return null; - } catch (NoSuchMethodException | InvocationTargetException e) { - try { - LOG.info("Invoking default constructor. ClassName = {}, interfaceName = {}.", className, - iface.getName()); - // fallback to default constructor - instance = this.getClass().getClassLoader().loadClass(className).asSubclass(iface).newInstance(); - } catch (InstantiationException | IllegalAccessException | ClassNotFoundException ex) { - LOG.error( - "Unable to invoke default constructor. ClassName = {}, interfaceName = {}, cause = {}, errorMessage = {}.", - className, iface.getName(), ex.getCause(), ex.getMessage()); - return null; - } - } - } catch (ClassNotFoundException ex) { - LOG.error("The class does not exist. ClassName = {}, interfaceName = {}.", className, iface.getName()); - return null; - } catch (SecurityException ex) { - LOG.error( - "Unable to load class due to a security violation. ClassName = {}, interfaceName = {}, cause = {}, errorMessage = {}.", - className, iface.getName(), ex.getCause(), ex.getMessage()); - return null; - } + @SuppressWarnings("unchecked") + private T loadClass(String className, Class iface, Class constructorArgClass, U props) { + T instance = null; + try { + LOG.info("Loading class. ClassName = {}, interfaceName = {}.", className, iface.getName()); + Class clazz = Class.forName(className); - return instance; - } + // check if method getInstance exists + Method method = clazz.getMethod("getInstance", new Class[]{}); + try { + LOG.info( + "Invoking getInstance() method. ClassName = {}, interfaceName = {}.", + className, + iface.getName()); + instance = (T) method.invoke(null, new Object[]{}); + } catch (IllegalArgumentException | InvocationTargetException | IllegalAccessException ex) { + LOG.error( + "Unable to invoke getInstance() method. " + + "ClassName = {}, interfaceName = {}, cause = {}, errorMessage = {}.", + className, + iface.getName(), + ex.getCause(), + ex.getMessage()); + return null; + } + } catch (NoSuchMethodException nsmex) { + try { + // check if constructor with constructor arg class parameter + // exists + LOG.info( + "Invoking constructor with {} argument. ClassName = {}, interfaceName = {}.", + constructorArgClass.getName(), + className, + iface.getName()); + instance = this.getClass().getClassLoader().loadClass(className).asSubclass(iface) + .getConstructor(constructorArgClass).newInstance(props); + } catch (InstantiationException | IllegalAccessException | ClassNotFoundException ex) { + LOG.warn( + "Unable to invoke constructor with {} argument. " + + "ClassName = {}, interfaceName = {}, cause = {}, errorMessage = {}.", + constructorArgClass.getName(), + className, + iface.getName(), + ex.getCause(), + ex.getMessage()); + return null; + } catch (NoSuchMethodException | InvocationTargetException e) { + try { + LOG.info( + "Invoking default constructor. ClassName = {}, interfaceName = {}.", + className, + iface.getName()); + // fallback to default constructor + instance = this.getClass().getClassLoader().loadClass(className).asSubclass(iface).newInstance(); + } catch (InstantiationException | IllegalAccessException | ClassNotFoundException ex) { + LOG.error( + "Unable to invoke default constructor. " + + "ClassName = {}, interfaceName = {}, cause = {}, errorMessage = {}.", + className, + iface.getName(), + ex.getCause(), + ex.getMessage()); + return null; + } + } + } catch (ClassNotFoundException ex) { + LOG.error("The class does not exist. ClassName = {}, interfaceName = {}.", className, iface.getName()); + return null; + } catch (SecurityException ex) { + LOG.error( + "Unable to load class due to a security violation. " + + "ClassName = {}, interfaceName = {}, cause = {}, errorMessage = {}.", + className, + iface.getName(), + ex.getCause(), + ex.getMessage()); + return null; + } + + return instance; + } public List getSubscriptions() { return m_sessionsStore.getSubscriptions(); diff --git a/broker/src/main/java/io/moquette/spi/impl/Qos0PublishHandler.java b/broker/src/main/java/io/moquette/spi/impl/Qos0PublishHandler.java index 33b8ba46..55f47a18 100644 --- a/broker/src/main/java/io/moquette/spi/impl/Qos0PublishHandler.java +++ b/broker/src/main/java/io/moquette/spi/impl/Qos0PublishHandler.java @@ -1,3 +1,4 @@ + package io.moquette.spi.impl; import io.moquette.server.netty.NettyUtils; @@ -9,9 +10,7 @@ import io.netty.channel.Channel; import io.netty.handler.codec.mqtt.MqttPublishMessage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.util.List; - import static io.moquette.spi.impl.ProtocolProcessor.asStoredMessage; class Qos0PublishHandler extends QosPublishHandler { @@ -24,9 +23,8 @@ class Qos0PublishHandler extends QosPublishHandler { private final MessagesPublisher publisher; public Qos0PublishHandler(IAuthorizator authorizator, SubscriptionsStore subscriptions, - IMessagesStore messagesStore, BrokerInterceptor interceptor, - MessagesPublisher messagesPublisher) { - super(authorizator); + IMessagesStore messagesStore, BrokerInterceptor interceptor, MessagesPublisher messagesPublisher) { + super(authorizator); this.subscriptions = subscriptions; this.m_messagesStore = messagesStore; this.m_interceptor = interceptor; @@ -34,33 +32,41 @@ class Qos0PublishHandler extends QosPublishHandler { } void receivedPublishQos0(Channel channel, MqttPublishMessage msg) { - //verify if topic can be write + // verify if topic can be write final String topic = msg.variableHeader().topicName(); if (checkWriteOnTopic(topic, channel)) { return; } - //route message to subscribers + // route message to subscribers IMessagesStore.StoredMessage toStoreMsg = asStoredMessage(msg); String clientID = NettyUtils.clientID(channel); toStoreMsg.setClientID(clientID); final int messageID = msg.variableHeader().messageId(); - if (LOG.isTraceEnabled()) { - LOG.trace("Sending publish message to subscribers. MqttClientId = {}, topic = {}, messageId = {}, payload = {}, subscriptionTree = {}.", - clientID, topic, messageID, DebugUtils.payload2Str(toStoreMsg.getMessage()), - subscriptions.dumpTree()); - } else { - LOG.info("Sending publish message to subscribers. MqttClientId = {}, topic = {}, messageId = {}.", clientID, - topic, messageID); - } - + if (LOG.isTraceEnabled()) { + LOG.trace( + "Sending publish message to subscribers. " + + "MqttClientId = {}, topic = {}, messageId = {}, payload = {}, subscriptionTree = {}.", + clientID, + topic, + messageID, + DebugUtils.payload2Str(toStoreMsg.getMessage()), + subscriptions.dumpTree()); + } else { + LOG.info( + "Sending publish message to subscribers. MqttClientId = {}, topic = {}, messageId = {}.", + clientID, + topic, + messageID); + } + List topicMatchingSubscriptions = subscriptions.matches(topic); this.publisher.publish2Subscribers(toStoreMsg, topicMatchingSubscriptions); if (msg.fixedHeader().isRetain()) { - //QoS == 0 && retain => clean old retained + // QoS == 0 && retain => clean old retained m_messagesStore.cleanRetained(topic); } diff --git a/broker/src/main/java/io/moquette/spi/impl/Qos1PublishHandler.java b/broker/src/main/java/io/moquette/spi/impl/Qos1PublishHandler.java index d9b72a58..8b0bf075 100644 --- a/broker/src/main/java/io/moquette/spi/impl/Qos1PublishHandler.java +++ b/broker/src/main/java/io/moquette/spi/impl/Qos1PublishHandler.java @@ -1,3 +1,4 @@ + package io.moquette.spi.impl; import io.moquette.server.ConnectionDescriptorStore; @@ -14,14 +15,13 @@ import io.netty.handler.codec.mqtt.MqttPubAckMessage; import io.netty.handler.codec.mqtt.MqttPublishMessage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.util.List; - import static io.moquette.spi.impl.ProtocolProcessor.asStoredMessage; import static io.netty.handler.codec.mqtt.MqttMessageIdVariableHeader.from; import static io.netty.handler.codec.mqtt.MqttQoS.AT_MOST_ONCE; class Qos1PublishHandler extends QosPublishHandler { + private static final Logger LOG = LoggerFactory.getLogger(Qos1PublishHandler.class); private final SubscriptionsStore subscriptions; @@ -31,10 +31,9 @@ class Qos1PublishHandler extends QosPublishHandler { private final MessagesPublisher publisher; public Qos1PublishHandler(IAuthorizator authorizator, SubscriptionsStore subscriptions, - IMessagesStore messagesStore, BrokerInterceptor interceptor, - ConnectionDescriptorStore connectionDescriptors, - String brokerPort, MessagesPublisher messagesPublisher) { - super(authorizator); + IMessagesStore messagesStore, BrokerInterceptor interceptor, + ConnectionDescriptorStore connectionDescriptors, String brokerPort, MessagesPublisher messagesPublisher) { + super(authorizator); this.subscriptions = subscriptions; this.m_messagesStore = messagesStore; this.m_interceptor = interceptor; @@ -43,7 +42,7 @@ class Qos1PublishHandler extends QosPublishHandler { } void receivedPublishQos1(Channel channel, MqttPublishMessage msg) { - //verify if topic can be write + // verify if topic can be write final String topic = msg.variableHeader().topicName(); if (checkWriteOnTopic(topic, channel)) { return; @@ -51,33 +50,41 @@ class Qos1PublishHandler extends QosPublishHandler { final int messageID = msg.variableHeader().messageId(); - //route message to subscribers + // route message to subscribers IMessagesStore.StoredMessage toStoreMsg = asStoredMessage(msg); String clientID = NettyUtils.clientID(channel); toStoreMsg.setClientID(clientID); - if (LOG.isTraceEnabled()) { - LOG.trace("Sending publish message to subscribers. MqttClientId = {}, topic = {}, messageId = {}, payload = {}, subscriptionTree = {}.", - clientID, topic, messageID, DebugUtils.payload2Str(toStoreMsg.getMessage()), - subscriptions.dumpTree()); - } else { - LOG.info("Sending publish message to subscribers. MqttClientId = {}, topic = {}, messageId = {}.", clientID, - topic, messageID); - } + if (LOG.isTraceEnabled()) { + LOG.trace( + "Sending publish message to subscribers. " + + "MqttClientId = {}, topic = {}, messageId = {}, payload = {}, subscriptionTree = {}.", + clientID, + topic, + messageID, + DebugUtils.payload2Str(toStoreMsg.getMessage()), + subscriptions.dumpTree()); + } else { + LOG.info( + "Sending publish message to subscribers. MqttClientId = {}, topic = {}, messageId = {}.", + clientID, + topic, + messageID); + } List topicMatchingSubscriptions = subscriptions.matches(topic); this.publisher.publish2Subscribers(toStoreMsg, topicMatchingSubscriptions); - //send PUBACK - //TODO Don't send PUBREC for Hz publish notification, if (msg.isLocal()) { - sendPubAck(clientID, messageID); -// } + // send PUBACK + // TODO Don't send PUBREC for Hz publish notification, if (msg.isLocal()) { + sendPubAck(clientID, messageID); + // } if (msg.fixedHeader().isRetain()) { if (!msg.payload().isReadable()) { m_messagesStore.cleanRetained(topic); } else { - //before wasn't stored + // before wasn't stored MessageGUID guid = m_messagesStore.storePublishForFuture(toStoreMsg); m_messagesStore.storeRetained(topic, guid); } @@ -94,14 +101,20 @@ class Qos1PublishHandler extends QosPublishHandler { try { if (connectionDescriptors == null) { - throw new RuntimeException("Internal bad error, found connectionDescriptors to null while it should be initialized, somewhere it's overwritten!!"); + throw new RuntimeException( + "Internal bad error, found connectionDescriptors to null while it should be initialized, " + + "somewhere it's overwritten!!"); } LOG.debug("clientIDs are {}", connectionDescriptors); if (!connectionDescriptors.isConnected(clientId)) { - throw new RuntimeException(String.format("Can't find a ConnectionDescriptor for client %s in cache %s", clientId, connectionDescriptors)); + throw new RuntimeException( + String.format( + "Can't find a ConnectionDescriptor for client %s in cache %s", + clientId, + connectionDescriptors)); } connectionDescriptors.sendMessage(pubAckMessage, messageID, clientId); - } catch(Throwable t) { + } catch (Throwable t) { LOG.error(null, t); } } diff --git a/broker/src/main/java/io/moquette/spi/impl/Qos2PublishHandler.java b/broker/src/main/java/io/moquette/spi/impl/Qos2PublishHandler.java index c020aa73..de76ada6 100644 --- a/broker/src/main/java/io/moquette/spi/impl/Qos2PublishHandler.java +++ b/broker/src/main/java/io/moquette/spi/impl/Qos2PublishHandler.java @@ -1,3 +1,4 @@ + package io.moquette.spi.impl; import io.moquette.server.ConnectionDescriptorStore; @@ -13,15 +14,13 @@ import io.netty.channel.Channel; import io.netty.handler.codec.mqtt.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.util.List; - import static io.moquette.spi.impl.ProtocolProcessor.asStoredMessage; import static io.moquette.spi.impl.Utils.messageId; import static io.netty.handler.codec.mqtt.MqttMessageIdVariableHeader.from; import static io.netty.handler.codec.mqtt.MqttQoS.AT_MOST_ONCE; -class Qos2PublishHandler extends QosPublishHandler { +class Qos2PublishHandler extends QosPublishHandler { private static final Logger LOG = LoggerFactory.getLogger(Qos1PublishHandler.class); @@ -33,10 +32,10 @@ class Qos2PublishHandler extends QosPublishHandler { private final MessagesPublisher publisher; public Qos2PublishHandler(IAuthorizator authorizator, SubscriptionsStore subscriptions, - IMessagesStore messagesStore, BrokerInterceptor interceptor, - ConnectionDescriptorStore connectionDescriptors, - ISessionsStore sessionsStore, String brokerPort, MessagesPublisher messagesPublisher) { - super(authorizator); + IMessagesStore messagesStore, BrokerInterceptor interceptor, + ConnectionDescriptorStore connectionDescriptors, ISessionsStore sessionsStore, String brokerPort, + MessagesPublisher messagesPublisher) { + super(authorizator); this.subscriptions = subscriptions; this.m_messagesStore = messagesStore; this.m_interceptor = interceptor; @@ -47,7 +46,7 @@ class Qos2PublishHandler extends QosPublishHandler { void receivedPublishQos2(Channel channel, MqttPublishMessage msg) { final String topic = msg.variableHeader().topicName(); - //check if the topic can be wrote + // check if the topic can be wrote if (checkWriteOnTopic(topic, channel)) { return; } @@ -57,23 +56,30 @@ class Qos2PublishHandler extends QosPublishHandler { String clientID = NettyUtils.clientID(channel); toStoreMsg.setClientID(clientID); - if (LOG.isTraceEnabled()) { - LOG.trace("Sending publish message to subscribers. MqttClientId = {}, topic = {}, messageId = {}, " + - "payload = {}, subscriptionTree = {}.", - clientID, topic, messageID, DebugUtils.payload2Str(toStoreMsg.getMessage()), - subscriptions.dumpTree()); - } else { - LOG.info("Sending publish message to subscribers. MqttClientId = {}, topic = {}, messageId = {}.", - clientID, topic, messageID); - } + if (LOG.isTraceEnabled()) { + LOG.trace( + "Sending publish message to subscribers. MqttClientId = {}, topic = {}, messageId = {}, " + + "payload = {}, subscriptionTree = {}.", + clientID, + topic, + messageID, + DebugUtils.payload2Str(toStoreMsg.getMessage()), + subscriptions.dumpTree()); + } else { + LOG.info( + "Sending publish message to subscribers. MqttClientId = {}, topic = {}, messageId = {}.", + clientID, + topic, + messageID); + } - //QoS2 + // QoS2 MessageGUID guid = m_messagesStore.storePublishForFuture(toStoreMsg); - //TODO Don't send PUBREC for Hz publish notification, if (msg.isLocal()) { - sendPubRec(clientID, messageID); - //} - //Next the client will send us a pub rel - //NB publish to subscribers for QoS 2 happen upon PUBREL from publisher + // TODO Don't send PUBREC for Hz publish notification, if (msg.isLocal()) { + sendPubRec(clientID, messageID); + // } + // Next the client will send us a pub rel + // NB publish to subscribers for QoS 2 happen upon PUBREL from publisher if (msg.fixedHeader().isRetain()) { if (msg.payload().readableBytes() == 0) { @@ -87,9 +93,9 @@ class Qos2PublishHandler extends QosPublishHandler { } /** - * Second phase of a publish QoS2 protocol, sent by publisher to the broker. Search the stored message and publish - * to all interested subscribers. - * */ + * Second phase of a publish QoS2 protocol, sent by publisher to the broker. Search the stored + * message and publish to all interested subscribers. + */ void processPubRel(Channel channel, MqttMessage msg) { String clientID = NettyUtils.clientID(channel); int messageID = messageId(msg); @@ -99,14 +105,22 @@ class Qos2PublishHandler extends QosPublishHandler { final String topic = evt.getTopic(); List topicMatchingSubscriptions = subscriptions.matches(topic); - if (LOG.isDebugEnabled()) { - LOG.debug("Sending publish message to subscribers. MqttClientId = {}, topic = {}, messageId = {}, payload = {}, subscriptionTree = {}.", - clientID, topic, messageID, DebugUtils.payload2Str(evt.getMessage()), - subscriptions.dumpTree()); - } else { - LOG.info("Sending publish message to subscribers. MqttClientId = {}, topic = {}, messageId = {}.", clientID, - topic, messageID); - } + if (LOG.isDebugEnabled()) { + LOG.debug( + "Sending publish message to subscribers. " + + "MqttClientId = {}, topic = {}, messageId = {}, payload = {}, subscriptionTree = {}.", + clientID, + topic, + messageID, + DebugUtils.payload2Str(evt.getMessage()), + subscriptions.dumpTree()); + } else { + LOG.info( + "Sending publish message to subscribers. MqttClientId = {}, topic = {}, messageId = {}.", + clientID, + topic, + messageID); + } this.publisher.publish2Subscribers(evt, topicMatchingSubscriptions); if (evt.isRetained()) { @@ -120,12 +134,11 @@ class Qos2PublishHandler extends QosPublishHandler { sendPubComp(clientID, messageID); } - private void sendPubRec(String clientID, int messageID) { LOG.debug("Sending PUBREC message. MqttClientId = {}, messageId = {}.", clientID, messageID); MqttFixedHeader fixedHeader = new MqttFixedHeader(MqttMessageType.PUBREC, false, AT_MOST_ONCE, false, 0); MqttMessage pubRecMessage = new MqttMessage(fixedHeader, from(messageID)); - connectionDescriptors.sendMessage(pubRecMessage,messageID, clientID); + connectionDescriptors.sendMessage(pubRecMessage, messageID, clientID); } private void sendPubComp(String clientID, int messageID) { diff --git a/broker/src/main/java/io/moquette/spi/impl/QosPublishHandler.java b/broker/src/main/java/io/moquette/spi/impl/QosPublishHandler.java index 6f5988f4..ab1af41a 100644 --- a/broker/src/main/java/io/moquette/spi/impl/QosPublishHandler.java +++ b/broker/src/main/java/io/moquette/spi/impl/QosPublishHandler.java @@ -1,30 +1,32 @@ + package io.moquette.spi.impl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import io.moquette.server.netty.NettyUtils; import io.moquette.spi.security.IAuthorizator; import io.netty.channel.Channel; abstract class QosPublishHandler { - - private static final Logger LOG = LoggerFactory.getLogger(QosPublishHandler.class); - - private final IAuthorizator m_authorizator; - - protected QosPublishHandler(IAuthorizator m_authorizator) { - this.m_authorizator = m_authorizator; - } - public boolean checkWriteOnTopic(String topic, Channel channel) { - String clientID = NettyUtils.clientID(channel); - String username = NettyUtils.userName(channel); - if (!m_authorizator.canWrite(topic, username, clientID)) { - LOG.error("The MQTT client is not authorized to publish on topic. MqttClientId = {}, topic = {}.", clientID, - topic); - return true; - } - return false; - } + private static final Logger LOG = LoggerFactory.getLogger(QosPublishHandler.class); + + private final IAuthorizator m_authorizator; + + protected QosPublishHandler(IAuthorizator m_authorizator) { + this.m_authorizator = m_authorizator; + } + + public boolean checkWriteOnTopic(String topic, Channel channel) { + String clientID = NettyUtils.clientID(channel); + String username = NettyUtils.userName(channel); + if (!m_authorizator.canWrite(topic, username, clientID)) { + LOG.error( + "The MQTT client is not authorized to publish on topic. MqttClientId = {}, topic = {}.", + clientID, + topic); + return true; + } + return false; + } } diff --git a/broker/src/main/java/io/moquette/spi/impl/Utils.java b/broker/src/main/java/io/moquette/spi/impl/Utils.java index af813ef5..12922d0e 100644 --- a/broker/src/main/java/io/moquette/spi/impl/Utils.java +++ b/broker/src/main/java/io/moquette/spi/impl/Utils.java @@ -1,9 +1,9 @@ + package io.moquette.spi.impl; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.mqtt.MqttMessage; import io.netty.handler.codec.mqtt.MqttMessageIdVariableHeader; - import java.util.Map; /** diff --git a/broker/src/main/java/io/moquette/spi/impl/security/ACLFileParser.java b/broker/src/main/java/io/moquette/spi/impl/security/ACLFileParser.java index 69812442..13648d42 100644 --- a/broker/src/main/java/io/moquette/spi/impl/security/ACLFileParser.java +++ b/broker/src/main/java/io/moquette/spi/impl/security/ACLFileParser.java @@ -13,29 +13,32 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl.security; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.io.*; import java.text.ParseException; /** - * Parses the acl configuration file. - * If a line starts with # it's comment. - * Blank lines are skipped. The format is "topic [read|write|readwrite] {topic name}" + * Parses the acl configuration file. If a line starts with # it's comment. Blank lines are skipped. + * The format is "topic [read|write|readwrite] {topic name}" * * @author andrea - * */ + */ public class ACLFileParser { + private static final Logger LOG = LoggerFactory.getLogger(ACLFileParser.class); /** * Parse the configuration from file. - * @param file to parse + * + * @param file + * to parse * @return the collector of authorizations form reader passed into. - * @throws ParseException if the format is not compliant. + * @throws ParseException + * if the format is not compliant. */ public static AuthorizationsCollector parse(File file) throws ParseException { if (file == null) { @@ -43,27 +46,37 @@ public class ACLFileParser { return AuthorizationsCollector.emptyImmutableCollector(); } if (!file.exists()) { - LOG.warn(String.format("parsing not existing file %s, so fallback on default configuration!", file.getAbsolutePath())); + LOG.warn( + String.format( + "parsing not existing file %s, so fallback on default configuration!", + file.getAbsolutePath())); return AuthorizationsCollector.emptyImmutableCollector(); } try { FileReader reader = new FileReader(file); return parse(reader); } catch (FileNotFoundException fex) { - LOG.warn(String.format("parsing not existing file %s, so fallback on default configuration!", file.getAbsolutePath()), fex); + LOG.warn( + String.format( + "parsing not existing file %s, so fallback on default configuration!", + file.getAbsolutePath()), + fex); return AuthorizationsCollector.emptyImmutableCollector(); } } /** * Parse the ACL configuration file - * @param reader to parse + * + * @param reader + * to parse * @return the collector of authorizations form reader passed into. - * @throws ParseException if the format is not compliant. + * @throws ParseException + * if the format is not compliant. */ public static AuthorizationsCollector parse(Reader reader) throws ParseException { if (reader == null) { - //just log and return default properties + // just log and return default properties LOG.warn("parsing NULL reader, so fallback on default configuration!"); return AuthorizationsCollector.emptyImmutableCollector(); } @@ -77,15 +90,15 @@ public class ACLFileParser { int commentMarker = line.indexOf('#'); if (commentMarker != -1) { if (commentMarker == 0) { - //skip its a comment + // skip its a comment continue; } else { - //it's a malformed comment + // it's a malformed comment throw new ParseException(line, commentMarker); } } else { if (line.isEmpty() || line.matches("^\\s*$")) { - //skip it's a black line + // skip it's a black line continue; } diff --git a/broker/src/main/java/io/moquette/spi/impl/security/AcceptAllAuthenticator.java b/broker/src/main/java/io/moquette/spi/impl/security/AcceptAllAuthenticator.java index 39898665..01bc91ca 100644 --- a/broker/src/main/java/io/moquette/spi/impl/security/AcceptAllAuthenticator.java +++ b/broker/src/main/java/io/moquette/spi/impl/security/AcceptAllAuthenticator.java @@ -1,3 +1,4 @@ + package io.moquette.spi.impl.security; import io.moquette.spi.security.IAuthenticator; @@ -6,6 +7,7 @@ import io.moquette.spi.security.IAuthenticator; * Created by andrea on 8/23/14. */ public class AcceptAllAuthenticator implements IAuthenticator { + public boolean checkValid(String clientId, String username, byte[] password) { return true; } diff --git a/broker/src/main/java/io/moquette/spi/impl/security/Authorization.java b/broker/src/main/java/io/moquette/spi/impl/security/Authorization.java index fc19e9db..9fefd3b0 100644 --- a/broker/src/main/java/io/moquette/spi/impl/security/Authorization.java +++ b/broker/src/main/java/io/moquette/spi/impl/security/Authorization.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl.security; import static io.moquette.spi.impl.security.Authorization.Permission.READWRITE; @@ -23,12 +24,13 @@ import static io.moquette.spi.impl.security.Authorization.Permission.READWRITE; * @author andrea */ public class Authorization { + protected final String topic; protected final Permission permission; /** * Access rights - * */ + */ enum Permission { READ, WRITE, READWRITE } @@ -48,13 +50,17 @@ public class Authorization { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; Authorization that = (Authorization) o; - if (permission != that.permission) return false; - if (!topic.equals(that.topic)) return false; + if (permission != that.permission) + return false; + if (!topic.equals(that.topic)) + return false; return true; } diff --git a/broker/src/main/java/io/moquette/spi/impl/security/AuthorizationsCollector.java b/broker/src/main/java/io/moquette/spi/impl/security/AuthorizationsCollector.java index 9db32b6e..0686028e 100644 --- a/broker/src/main/java/io/moquette/spi/impl/security/AuthorizationsCollector.java +++ b/broker/src/main/java/io/moquette/spi/impl/security/AuthorizationsCollector.java @@ -13,19 +13,19 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl.security; import io.moquette.spi.impl.subscriptions.SubscriptionsStore; import io.moquette.spi.security.IAuthorizator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.text.ParseException; import java.util.*; /** - * Used by the ACLFileParser to push all authorizations it finds. - * ACLAuthorizator uses it in read mode to check it topics matches the ACLs. + * Used by the ACLFileParser to push all authorizations it finds. ACLAuthorizator uses it in read + * mode to check it topics matches the ACLs. * * Not thread safe. * @@ -53,11 +53,12 @@ class AuthorizationsCollector implements IAuthorizator { void parse(String line) throws ParseException { Authorization acl = parseAuthLine(line); if (acl == null) { - //skip it's a user + // skip it's a user return; } if (m_parsingUsersSpecificSection) { - //TODO in java 8 switch to m_userAuthorizations.putIfAbsent(m_currentUser, new ArrayList()); + // TODO in java 8 switch to m_userAuthorizations.putIfAbsent(m_currentUser, new + // ArrayList()); if (!m_userAuthorizations.containsKey(m_currentUser)) { m_userAuthorizations.put(m_currentUser, new ArrayList()); } @@ -93,10 +94,10 @@ class AuthorizationsCollector implements IAuthorizator { private Authorization createAuthorization(String line, String[] tokens) throws ParseException { if (tokens.length > 2) { - //if the tokenized lines has 3 token the second must be the permission + // if the tokenized lines has 3 token the second must be the permission try { Authorization.Permission permission = Authorization.Permission.valueOf(tokens[1].toUpperCase()); - //bring topic with all original spacing + // bring topic with all original spacing String topic = line.substring(line.indexOf(tokens[2])); return new Authorization(topic, permission); @@ -119,7 +120,7 @@ class AuthorizationsCollector implements IAuthorizator { } private boolean canDoOperation(String topic, Authorization.Permission permission, String username, String client) { - if (matchACL(m_globalAuthorizations, topic, permission)) { + if (matchACL(m_globalAuthorizations, topic, permission)) { return true; } @@ -137,7 +138,7 @@ class AuthorizationsCollector implements IAuthorizator { if (isNotEmpty(username)) { if (m_userAuthorizations.containsKey(username)) { List auths = m_userAuthorizations.get(username); - if (matchACL(auths, topic, permission)) { + if (matchACL(auths, topic, permission)) { return true; } } diff --git a/broker/src/main/java/io/moquette/spi/impl/security/DBAuthenticator.java b/broker/src/main/java/io/moquette/spi/impl/security/DBAuthenticator.java index e1cd774f..4e92b68d 100644 --- a/broker/src/main/java/io/moquette/spi/impl/security/DBAuthenticator.java +++ b/broker/src/main/java/io/moquette/spi/impl/security/DBAuthenticator.java @@ -1,3 +1,4 @@ + package io.moquette.spi.impl.security; import io.moquette.BrokerConstants; @@ -6,14 +7,12 @@ import io.moquette.spi.security.IAuthenticator; import org.apache.commons.codec.binary.Hex; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.sql.*; /** - * Load user credentials from a SQL database. - * sql driver must be provided at runtime + * Load user credentials from a SQL database. sql driver must be provided at runtime * * @author mackristof */ @@ -25,30 +24,34 @@ public class DBAuthenticator implements IAuthenticator { private final MessageDigest messageDigest; private final PreparedStatement preparedStatement; - - - - public DBAuthenticator(IConfig conf){ - this(conf.getProperty(BrokerConstants.DB_AUTHENTICATOR_DRIVER, ""), - conf.getProperty(BrokerConstants.DB_AUTHENTICATOR_URL,""), - conf.getProperty(BrokerConstants.DB_AUTHENTICATOR_QUERY, ""), - conf.getProperty(BrokerConstants.DB_AUTHENTICATOR_DIGEST,"")); + public DBAuthenticator(IConfig conf) { + this( + conf.getProperty(BrokerConstants.DB_AUTHENTICATOR_DRIVER, ""), + conf.getProperty(BrokerConstants.DB_AUTHENTICATOR_URL, ""), + conf.getProperty(BrokerConstants.DB_AUTHENTICATOR_QUERY, ""), + conf.getProperty(BrokerConstants.DB_AUTHENTICATOR_DIGEST, "")); } - /** provide authenticator from SQL database - * @param driver : jdbc driver class like : "org.postgresql.Driver" - * @param jdbcUrl : jdbc url like : "jdbc:postgresql://host:port/dbname" - * @param sqlQuery : sql query like : "SELECT PASSWORD FROM USER WHERE LOGIN=?" - * @param digestMethod : password encoding algorithm : "MD5", "SHA-1", "SHA-256" + /** + * provide authenticator from SQL database + * + * @param driver + * : jdbc driver class like : "org.postgresql.Driver" + * @param jdbcUrl + * : jdbc url like : "jdbc:postgresql://host:port/dbname" + * @param sqlQuery + * : sql query like : "SELECT PASSWORD FROM USER WHERE LOGIN=?" + * @param digestMethod + * : password encoding algorithm : "MD5", "SHA-1", "SHA-256" */ - public DBAuthenticator(String driver, String jdbcUrl, String sqlQuery, String digestMethod){ + public DBAuthenticator(String driver, String jdbcUrl, String sqlQuery, String digestMethod) { try { Class.forName(driver); final Connection connection = DriverManager.getConnection(jdbcUrl); - this.messageDigest = MessageDigest.getInstance(digestMethod); + this.messageDigest = MessageDigest.getInstance(digestMethod); this.preparedStatement = connection.prepareStatement(sqlQuery); - } catch (ClassNotFoundException cnfe){ + } catch (ClassNotFoundException cnfe) { LOG.error(String.format("Can't find driver %s", driver), cnfe); throw new RuntimeException(cnfe); } catch (SQLException sqle) { @@ -67,11 +70,11 @@ public class DBAuthenticator implements IAuthenticator { LOG.info("username or password was null"); return false; } - ResultSet r= null; + ResultSet r = null; try { - this.preparedStatement.setString(1,username); + this.preparedStatement.setString(1, username); r = this.preparedStatement.executeQuery(); - if(r.next()) { + if (r.next()) { final String foundPwq = r.getString(1); messageDigest.update(password); byte[] digest = messageDigest.digest(); diff --git a/broker/src/main/java/io/moquette/spi/impl/security/DenyAllAuthorizator.java b/broker/src/main/java/io/moquette/spi/impl/security/DenyAllAuthorizator.java index bd336e5c..614a562d 100644 --- a/broker/src/main/java/io/moquette/spi/impl/security/DenyAllAuthorizator.java +++ b/broker/src/main/java/io/moquette/spi/impl/security/DenyAllAuthorizator.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl.security; import io.moquette.spi.security.IAuthorizator; @@ -21,6 +22,7 @@ import io.moquette.spi.security.IAuthorizator; * @author andrea */ public class DenyAllAuthorizator implements IAuthorizator { + @Override public boolean canWrite(String topic, String user, String client) { return true; @@ -30,4 +32,4 @@ public class DenyAllAuthorizator implements IAuthorizator { public boolean canRead(String topic, String user, String client) { return true; } -} \ No newline at end of file +} diff --git a/broker/src/main/java/io/moquette/spi/impl/security/FileAuthenticator.java b/broker/src/main/java/io/moquette/spi/impl/security/FileAuthenticator.java index 2d97d16b..b8e5fc82 100644 --- a/broker/src/main/java/io/moquette/spi/impl/security/FileAuthenticator.java +++ b/broker/src/main/java/io/moquette/spi/impl/security/FileAuthenticator.java @@ -13,19 +13,23 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl.security; import io.moquette.server.config.FileResourceLoader; /** - * Load user credentials from a text file. - * Each line of the file is formatted as "[username]:[sha256(password)]". The username mustn't contains : char. + * Load user credentials from a text file. Each line of the file is formatted as + * "[username]:[sha256(password)]". The username mustn't contains : char. * * To encode your password from command line on Linux systems, you could use: + * *
  *     echo -n "yourpassword" | sha256sum
  * 
- * NB -n is important because echo append a newline by default at the of string. -n avoid this behaviour. + * + * NB -n is important because echo append a newline by default at the of string. -n avoid this + * behaviour. * * @author andrea * @deprecated user {@link ResourceAuthenticator} instead diff --git a/broker/src/main/java/io/moquette/spi/impl/security/PermitAllAuthorizator.java b/broker/src/main/java/io/moquette/spi/impl/security/PermitAllAuthorizator.java index 1447da07..80d45666 100644 --- a/broker/src/main/java/io/moquette/spi/impl/security/PermitAllAuthorizator.java +++ b/broker/src/main/java/io/moquette/spi/impl/security/PermitAllAuthorizator.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl.security; import io.moquette.spi.security.IAuthorizator; @@ -21,6 +22,7 @@ import io.moquette.spi.security.IAuthorizator; * @author andrea */ public class PermitAllAuthorizator implements IAuthorizator { + @Override public boolean canWrite(String topic, String user, String client) { return true; diff --git a/broker/src/main/java/io/moquette/spi/impl/security/ResourceAuthenticator.java b/broker/src/main/java/io/moquette/spi/impl/security/ResourceAuthenticator.java index 38cbb60a..02d8bdc3 100644 --- a/broker/src/main/java/io/moquette/spi/impl/security/ResourceAuthenticator.java +++ b/broker/src/main/java/io/moquette/spi/impl/security/ResourceAuthenticator.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl.security; import io.moquette.server.config.IResourceLoader; @@ -20,7 +21,6 @@ import io.moquette.spi.security.IAuthenticator; import org.apache.commons.codec.digest.DigestUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; @@ -31,14 +31,17 @@ import java.util.HashMap; import java.util.Map; /** - * Load user credentials from a text resource. - * Each line of the file is formatted as "[username]:[sha256(password)]". The username mustn't contains : char. + * Load user credentials from a text resource. Each line of the file is formatted as + * "[username]:[sha256(password)]". The username mustn't contains : char. * * To encode your password from command line on Linux systems, you could use: + * *
  *     echo -n "yourpassword" | sha256sum
  * 
- * NB -n is important because echo append a newline by default at the of string. -n avoid this behaviour. + * + * NB -n is important because echo append a newline by default at the of string. -n avoid this + * behaviour. * * @author andrea */ @@ -63,24 +66,23 @@ public class ResourceAuthenticator implements IAuthenticator { reader = resourceLoader.loadResource(resourceName); if (reader == null) { LOG.warn(String.format("Parsing not existing %s %s", resourceLoader.getName(), resourceName)); - } - else { + } else { parse(reader); } - } - catch (IResourceLoader.ResourceIsDirectoryException e) { + } catch (IResourceLoader.ResourceIsDirectoryException e) { LOG.warn(String.format("Trying to parse directory %s", resourceName)); - } - catch (ParseException pex) { - LOG.warn(String.format("Format error in parsing password %s %s", resourceLoader.getName(), resourceName), pex); + } catch (ParseException pex) { + LOG.warn( + String.format("Format error in parsing password %s %s", resourceLoader.getName(), resourceName), + pex); } } - + private void parse(Reader reader) throws ParseException { if (reader == null) { return; } - + BufferedReader br = new BufferedReader(reader); String line; try { @@ -88,23 +90,23 @@ public class ResourceAuthenticator implements IAuthenticator { int commentMarker = line.indexOf('#'); if (commentMarker != -1) { if (commentMarker == 0) { - //skip its a comment + // skip its a comment continue; } else { - //it's a malformed comment + // it's a malformed comment throw new ParseException(line, commentMarker); } } else { if (line.isEmpty() || line.matches("^\\s*$")) { - //skip it's a black line + // skip it's a black line continue; } - - //split till the first space + + // split till the first space int delimiterIdx = line.indexOf(':'); String username = line.substring(0, delimiterIdx).trim(); String password = line.substring(delimiterIdx + 1).trim(); - + m_identities.put(username, password); } } @@ -126,5 +128,5 @@ public class ResourceAuthenticator implements IAuthenticator { String encodedPasswd = DigestUtils.sha256Hex(password); return foundPwq.equals(encodedPasswd); } - + } diff --git a/broker/src/main/java/io/moquette/spi/impl/subscriptions/Subscription.java b/broker/src/main/java/io/moquette/spi/impl/subscriptions/Subscription.java index 98c066c0..f2370236 100644 --- a/broker/src/main/java/io/moquette/spi/impl/subscriptions/Subscription.java +++ b/broker/src/main/java/io/moquette/spi/impl/subscriptions/Subscription.java @@ -13,28 +13,27 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl.subscriptions; import io.moquette.spi.ISessionsStore.ClientTopicCouple; import io.netty.handler.codec.mqtt.MqttQoS; - import java.io.Serializable; /** - * Maintain the information about which Topic a certain ClientID is subscribed - * and at which QoS - * - * + * Maintain the information about which Topic a certain ClientID is subscribed and at which QoS + * + * * @author andrea */ public final class Subscription implements Serializable { private static final long serialVersionUID = -3383457629635732794L; - final MqttQoS requestedQos; //max QoS acceptable + final MqttQoS requestedQos; // max QoS acceptable final String clientId; final String topicFilter; final boolean active; - + public Subscription(String clientId, String topicFilter, MqttQoS requestedQos) { this.requestedQos = requestedQos; this.clientId = clientId; @@ -67,14 +66,16 @@ public final class Subscription implements Serializable { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; Subscription that = (Subscription) o; - if (clientId != null ? !clientId.equals(that.clientId) : that.clientId != null) return false; + if (clientId != null ? !clientId.equals(that.clientId) : that.clientId != null) + return false; return !(topicFilter != null ? !topicFilter.equals(that.topicFilter) : that.topicFilter != null); - } @Override @@ -86,8 +87,12 @@ public final class Subscription implements Serializable { @Override public String toString() { - return String.format("[filter:%s, cliID: %s, qos: %s, active: %s]", this.topicFilter, this.clientId, - this.requestedQos, this.active); + return String.format( + "[filter:%s, cliID: %s, qos: %s, active: %s]", + this.topicFilter, + this.clientId, + this.requestedQos, + this.active); } @Override diff --git a/broker/src/main/java/io/moquette/spi/impl/subscriptions/SubscriptionsStore.java b/broker/src/main/java/io/moquette/spi/impl/subscriptions/SubscriptionsStore.java index 24d8904a..3353e22e 100644 --- a/broker/src/main/java/io/moquette/spi/impl/subscriptions/SubscriptionsStore.java +++ b/broker/src/main/java/io/moquette/spi/impl/subscriptions/SubscriptionsStore.java @@ -13,13 +13,13 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl.subscriptions; import io.moquette.spi.ISessionsStore; import io.moquette.spi.ISessionsStore.ClientTopicCouple; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.text.ParseException; import java.util.*; import java.util.concurrent.LinkedBlockingDeque; @@ -33,6 +33,7 @@ import java.util.concurrent.atomic.AtomicReference; public class SubscriptionsStore { public static class NodeCouple { + final TreeNode root; final TreeNode createdNode; @@ -44,28 +45,34 @@ public class SubscriptionsStore { /** * Check if the topic filter of the subscription is well formed - * @param topicFilter the filter to validate + * + * @param topicFilter + * the filter to validate * @return true if it's correct. - * */ + */ public static boolean validate(String topicFilter) { try { parseTopic(topicFilter); return true; - } catch (ParseException pex) { - LOG.warn("The topic filter is malformed. TopicFilter = {}, cause = {}, errorMessage = {}.", topicFilter, - pex.getCause(), pex.getMessage()); - return false; - } + } catch (ParseException pex) { + LOG.warn( + "The topic filter is malformed. TopicFilter = {}, cause = {}, errorMessage = {}.", + topicFilter, + pex.getCause(), + pex.getMessage()); + return false; + } } public interface IVisitor { + void visit(TreeNode node, int deep); - + T getResult(); } - + private class DumpTreeVisitor implements IVisitor { - + String s = ""; @Override @@ -76,14 +83,15 @@ public class SubscriptionsStore { subScriptionsStr += indentTabs + couple.toString() + "\n"; } s += node.getToken() == null ? "" : node.getToken().toString(); - s += "\n" + (node.m_subscriptions.isEmpty() ? indentTabs : "") + subScriptionsStr /*+ "\n"*/; + s += "\n" + (node.m_subscriptions.isEmpty() ? indentTabs : "") + + subScriptionsStr /* + "\n" */; } private String indentTabs(int deep) { String s = ""; - for (int i=0; i < deep; i++) { + for (int i = 0; i < deep; i++) { s += "\t"; -// s += "--"; + // s += "--"; } return s; } @@ -93,27 +101,32 @@ public class SubscriptionsStore { return s; } } - + private AtomicReference subscriptions = new AtomicReference<>(new TreeNode()); private static final Logger LOG = LoggerFactory.getLogger(SubscriptionsStore.class); private volatile ISessionsStore m_sessionsStore; /** - * Initialize the subscription tree with the list of subscriptions. - * Maintained for compatibility reasons. - * @param sessionsStore to be used as backing store from the subscription store. + * Initialize the subscription tree with the list of subscriptions. Maintained for compatibility + * reasons. + * + * @param sessionsStore + * to be used as backing store from the subscription store. */ public void init(ISessionsStore sessionsStore) { LOG.info("Initializing subscriptions store..."); m_sessionsStore = sessionsStore; List subscriptions = sessionsStore.listAllSubscriptions(); - //reload any subscriptions persisted + // reload any subscriptions persisted if (LOG.isTraceEnabled()) { LOG.trace("Reloading all stored subscriptions. SubscriptionTree = {}.", dumpTree()); } for (ClientTopicCouple clientTopic : subscriptions) { - LOG.info("Re-subscribing client to topic. ClientId = {}, topicFilter = {}.", clientTopic.clientID, clientTopic.topicFilter); + LOG.info( + "Re-subscribing client to topic. ClientId = {}, topicFilter = {}.", + clientTopic.clientID, + clientTopic.topicFilter); add(clientTopic); } if (LOG.isTraceEnabled()) { @@ -122,30 +135,33 @@ public class SubscriptionsStore { } public void add(ClientTopicCouple newSubscription) { - /* - * The topic filters have already been validated at the ProtocolProcessor. We can assume they are valid. - */ + /* + * The topic filters have already been validated at the ProtocolProcessor. We can assume + * they are valid. + */ TreeNode oldRoot; NodeCouple couple; do { oldRoot = subscriptions.get(); couple = recreatePath(newSubscription.topicFilter, oldRoot); - couple.createdNode.addSubscription(newSubscription); //createdNode could be null? - //spin lock repeating till we can, swap root, if can't swap just re-do the operation - } while(!subscriptions.compareAndSet(oldRoot, couple.root)); + couple.createdNode.addSubscription(newSubscription); // createdNode could be null? + // spin lock repeating till we can, swap root, if can't swap just re-do the operation + } while (!subscriptions.compareAndSet(oldRoot, couple.root)); LOG.debug("A subscription has been added. Root = {}, oldRoot = {}.", couple.root, oldRoot); } - protected NodeCouple recreatePath(String topic, final TreeNode oldRoot) { List tokens; try { tokens = parseTopic(topic); } catch (ParseException ex) { - //TODO handle the parse exception - LOG.error("The topic is malformed. Topic = {}, cause = {}, errorMessage = {}.", topic, ex.getCause(), - ex.getMessage()); - throw new IllegalArgumentException(ex.getMessage()); + // TODO handle the parse exception + LOG.error( + "The topic is malformed. Topic = {}, cause = {}, errorMessage = {}.", + topic, + ex.getCause(), + ex.getMessage()); + throw new IllegalArgumentException(ex.getMessage()); } final TreeNode newRoot = oldRoot.copy(); @@ -154,15 +170,15 @@ public class SubscriptionsStore { for (Token token : tokens) { TreeNode matchingChildren; - //check if a children with the same token already exists + // check if a children with the same token already exists if ((matchingChildren = current.childWithToken(token)) != null) { - //copy the traversed node + // copy the traversed node current = matchingChildren.copy(); - //update the child just added in the children list + // update the child just added in the children list parent.updateChild(matchingChildren, current); parent = current; } else { - //create a new node for the newly inserted token + // create a new node for the newly inserted token matchingChildren = new TreeNode(); matchingChildren.setToken(token); current.addChild(matchingChildren); @@ -173,9 +189,10 @@ public class SubscriptionsStore { } public void removeSubscription(String topic, String clientID) { - /* - * The topic filters have already been validated at the ProtocolProcessor. We can assume they are valid. - */ + /* + * The topic filters have already been validated at the ProtocolProcessor. We can assume + * they are valid. + */ TreeNode oldRoot; NodeCouple couple; do { @@ -183,14 +200,16 @@ public class SubscriptionsStore { couple = recreatePath(topic, oldRoot); couple.createdNode.remove(new ClientTopicCouple(clientID, topic)); - //spin lock repeating till we can, swap root, if can't swap just re-do the operation - } while(!subscriptions.compareAndSet(oldRoot, couple.root)); + // spin lock repeating till we can, swap root, if can't swap just re-do the operation + } while (!subscriptions.compareAndSet(oldRoot, couple.root)); } - + /** - * Visit the topics tree to remove matching subscriptions with clientID. - * It's a mutating structure operation so create a new subscription tree (partial or total). - * @param clientID the client ID to remove. + * Visit the topics tree to remove matching subscriptions with clientID. It's a mutating + * structure operation so create a new subscription tree (partial or total). + * + * @param clientID + * the client ID to remove. */ public void removeForClient(String clientID) { TreeNode oldRoot; @@ -198,17 +217,17 @@ public class SubscriptionsStore { do { oldRoot = subscriptions.get(); newRoot = oldRoot.removeClientSubscriptions(clientID); - //spin lock repeating till we can, swap root, if can't swap just re-do the operation - } while(!subscriptions.compareAndSet(oldRoot, newRoot)); + // spin lock repeating till we can, swap root, if can't swap just re-do the operation + } while (!subscriptions.compareAndSet(oldRoot, newRoot)); } - /** - * Given a topic string return the clients subscriptions that matches it. - * Topic string can't contain character # and + because they are reserved to - * listeners subscriptions, and not topic publishing. + * Given a topic string return the clients subscriptions that matches it. Topic string can't + * contain character # and + because they are reserved to listeners subscriptions, and not topic + * publishing. * - * @param topic to use fo searching matching subscriptions. + * @param topic + * to use fo searching matching subscriptions. * @return the list of matching subscriptions, or empty if not matching. */ public List matches(String topic) { @@ -216,8 +235,12 @@ public class SubscriptionsStore { try { tokens = parseTopic(topic); } catch (ParseException ex) { - //TODO handle the parse exception - LOG.warn("The topic is malformed. Topic = {}, cause = {}, errorMessage = {}.", topic, ex.getCause(), ex.getMessage()); + // TODO handle the parse exception + LOG.warn( + "The topic is malformed. Topic = {}, cause = {}, errorMessage = {}.", + topic, + ex.getCause(), + ex.getMessage()); return Collections.emptyList(); } @@ -225,16 +248,16 @@ public class SubscriptionsStore { List matchingSubs = new ArrayList<>(); subscriptions.get().matches(tokenQueue, matchingSubs); - //remove the overlapping subscriptions, selecting ones with greatest qos + // remove the overlapping subscriptions, selecting ones with greatest qos Map subsForClient = new HashMap<>(); for (ClientTopicCouple matchingCouple : matchingSubs) { Subscription existingSub = subsForClient.get(matchingCouple.clientID); Subscription sub = m_sessionsStore.getSubscription(matchingCouple); if (sub == null) { - //if the m_sessionStore hasn't the sub because the client disconnected + // if the m_sessionStore hasn't the sub because the client disconnected continue; } - //update the selected subscriptions if not present or if has a greater qos + // update the selected subscriptions if not present or if has a greater qos if (existingSub == null || existingSub.getRequestedQos().value() < sub.getRequestedQos().value()) { subsForClient.put(matchingCouple.clientID, sub); } @@ -249,13 +272,13 @@ public class SubscriptionsStore { public int size() { return subscriptions.get().size(); } - + public String dumpTree() { DumpTreeVisitor visitor = new DumpTreeVisitor(); bfsVisit(subscriptions.get(), visitor, 0); return visitor.getResult(); } - + private void bfsVisit(TreeNode node, IVisitor visitor, int deep) { if (node == null) { return; @@ -265,20 +288,23 @@ public class SubscriptionsStore { bfsVisit(child, visitor, ++deep); } } - + /** * Verify if the 2 topics matching respecting the rules of MQTT Appendix A - * @param msgTopic the topic to match from the message - * @param subscriptionTopic the topic filter of the subscription + * + * @param msgTopic + * the topic to match from the message + * @param subscriptionTopic + * the topic filter of the subscription * @return true if the two topics match. */ - //TODO reimplement with iterators or with queues + // TODO reimplement with iterators or with queues public static boolean matchTopics(String msgTopic, String subscriptionTopic) { try { List msgTokens = SubscriptionsStore.parseTopic(msgTopic); List subscriptionTokens = SubscriptionsStore.parseTopic(subscriptionTopic); int i = 0; - for (; i< subscriptionTokens.size(); i++) { + for (; i < subscriptionTokens.size(); i++) { Token subToken = subscriptionTokens.get(i); if (subToken != Token.MULTI && subToken != Token.SINGLE) { if (i >= msgTokens.size()) { @@ -293,23 +319,27 @@ public class SubscriptionsStore { return true; } if (subToken == Token.SINGLE) { - //skip a step forward + // skip a step forward } } } - //if last token was a SINGLE then treat it as an empty -// if (subToken == Token.SINGLE && (i - msgTokens.size() == 1)) { -// i--; -// } + // if last token was a SINGLE then treat it as an empty + // if (subToken == Token.SINGLE && (i - msgTokens.size() == 1)) { + // i--; + // } return i == msgTokens.size(); } catch (ParseException ex) { - LOG.error( - "The message topic, the subscription topic or both are malformed. MsgTopic = {}, subscriptionTopic = {}, cause = {}, errorMessage = {}.", - msgTopic, subscriptionTopic, ex.getCause(), ex.getMessage()); - throw new IllegalStateException(ex.getMessage()); + LOG.error( + "The message topic, the subscription topic or both are malformed. " + + "MsgTopic = {}, subscriptionTopic = {}, cause = {}, errorMessage = {}.", + msgTopic, + subscriptionTopic, + ex.getCause(), + ex.getMessage()); + throw new IllegalStateException(ex.getMessage()); } } - + protected static List parseTopic(String topic) throws ParseException { List res = new ArrayList<>(); String[] splitted = topic.split("/"); @@ -317,26 +347,29 @@ public class SubscriptionsStore { if (splitted.length == 0) { res.add(Token.EMPTY); } - + if (topic.endsWith("/")) { - //Add a fictious space + // Add a fictious space String[] newSplitted = new String[splitted.length + 1]; - System.arraycopy(splitted, 0, newSplitted, 0, splitted.length); + System.arraycopy(splitted, 0, newSplitted, 0, splitted.length); newSplitted[splitted.length] = ""; splitted = newSplitted; } - + for (int i = 0; i < splitted.length; i++) { String s = splitted[i]; if (s.isEmpty()) { -// if (i != 0) { -// throw new ParseException("Bad format of topic, expetec topic name between separators", i); -// } + // if (i != 0) { + // throw new ParseException("Bad format of topic, expetec topic name between + // separators", i); + // } res.add(Token.EMPTY); } else if (s.equals("#")) { - //check that multi is the last symbol + // check that multi is the last symbol if (i != splitted.length - 1) { - throw new ParseException("Bad format of topic, the multi symbol (#) has to be the last one after a separator", i); + throw new ParseException( + "Bad format of topic, the multi symbol (#) has to be the last one after a separator", + i); } res.add(Token.MULTI); } else if (s.contains("#")) { diff --git a/broker/src/main/java/io/moquette/spi/impl/subscriptions/Token.java b/broker/src/main/java/io/moquette/spi/impl/subscriptions/Token.java index 14189dc9..3efbd652 100644 --- a/broker/src/main/java/io/moquette/spi/impl/subscriptions/Token.java +++ b/broker/src/main/java/io/moquette/spi/impl/subscriptions/Token.java @@ -13,11 +13,12 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl.subscriptions; /** * Internal use only class. - * */ + */ public class Token { static final Token EMPTY = new Token(""); @@ -71,4 +72,4 @@ public class Token { public String toString() { return name; } -} \ No newline at end of file +} diff --git a/broker/src/main/java/io/moquette/spi/impl/subscriptions/TreeNode.java b/broker/src/main/java/io/moquette/spi/impl/subscriptions/TreeNode.java index 12762b0d..3be392b5 100644 --- a/broker/src/main/java/io/moquette/spi/impl/subscriptions/TreeNode.java +++ b/broker/src/main/java/io/moquette/spi/impl/subscriptions/TreeNode.java @@ -13,10 +13,10 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl.subscriptions; import io.moquette.spi.ISessionsStore.ClientTopicCouple; - import java.util.*; import java.util.concurrent.LinkedBlockingQueue; @@ -24,7 +24,7 @@ class TreeNode { Token m_token; List m_children = new ArrayList<>(); - //TODO move to set of ClientIDthe set of clientIDs that has subscriptions to this topic + // TODO move to set of ClientIDthe set of clientIDs that has subscriptions to this topic Set m_subscriptions = new HashSet<>(); TreeNode() { @@ -47,9 +47,8 @@ class TreeNode { } /** - * Creates a shallow copy of the current node. - * Copy the token and the children. - * */ + * Creates a shallow copy of the current node. Copy the token and the children. + */ TreeNode copy() { final TreeNode copy = new TreeNode(); copy.m_children = new ArrayList<>(m_children); @@ -59,8 +58,7 @@ class TreeNode { } /** - * Search for children that has the specified token, if not found return - * null; + * Search for children that has the specified token, if not found return null; */ TreeNode childWithToken(Token token) { for (TreeNode child : m_children) { @@ -85,14 +83,14 @@ class TreeNode { m_subscriptions.remove(clientTopicCouple); } - //TODO smell a query method that return the result modifing the parameter (matchingSubs) + // TODO smell a query method that return the result modifing the parameter (matchingSubs) void matches(Queue tokens, List matchingSubs) { Token t = tokens.poll(); - //check if t is null <=> tokens finished + // check if t is null <=> tokens finished if (t == null) { matchingSubs.addAll(m_subscriptions); - //check if it has got a MULTI child and add its subscriptions + // check if it has got a MULTI child and add its subscriptions for (TreeNode n : m_children) { if (n.getToken() == Token.MULTI || n.getToken() == Token.SINGLE) { matchingSubs.addAll(n.subscriptions()); @@ -102,7 +100,7 @@ class TreeNode { return; } - //we are on MULTI, than add subscriptions and return + // we are on MULTI, than add subscriptions and return if (m_token == Token.MULTI) { matchingSubs.addAll(m_subscriptions); return; @@ -110,10 +108,10 @@ class TreeNode { for (TreeNode n : m_children) { if (n.getToken().match(t)) { - //Create a copy of token, else if navigate 2 sibling it - //consumes 2 elements on the queue instead of one + // Create a copy of token, else if navigate 2 sibling it + // consumes 2 elements on the queue instead of one n.matches(new LinkedBlockingQueue<>(tokens), matchingSubs); - //TODO don't create a copy n.matches(tokens, matchingSubs); + // TODO don't create a copy n.matches(tokens, matchingSubs); } } } @@ -131,9 +129,9 @@ class TreeNode { /** * Create a copied subtree rooted on this node but purged of clientID's subscriptions. - * */ + */ TreeNode removeClientSubscriptions(String clientID) { - //collect what to delete and then delete to avoid ConcurrentModification + // collect what to delete and then delete to avoid ConcurrentModification TreeNode newSubRoot = this.copy(); List subsToRemove = new ArrayList<>(); for (ClientTopicCouple s : newSubRoot.m_subscriptions) { @@ -146,7 +144,7 @@ class TreeNode { newSubRoot.m_subscriptions.remove(s); } - //go deep + // go deep List newChildren = new ArrayList<>(newSubRoot.m_children.size()); for (TreeNode child : newSubRoot.m_children) { newChildren.add(child.removeClientSubscriptions(clientID)); diff --git a/broker/src/main/java/io/moquette/spi/persistence/MapDBMessagesStore.java b/broker/src/main/java/io/moquette/spi/persistence/MapDBMessagesStore.java index 172e0a2c..62e6545b 100644 --- a/broker/src/main/java/io/moquette/spi/persistence/MapDBMessagesStore.java +++ b/broker/src/main/java/io/moquette/spi/persistence/MapDBMessagesStore.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.persistence; import io.moquette.spi.IMatchingCondition; @@ -21,7 +22,6 @@ import io.moquette.spi.MessageGUID; import org.mapdb.DB; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.util.*; import java.util.concurrent.ConcurrentMap; @@ -36,12 +36,11 @@ class MapDBMessagesStore implements IMessagesStore { private DB m_db; - //maps clientID -> guid + // maps clientID -> guid private ConcurrentMap m_retainedStore; - //maps guid to message, it's message store + // maps guid to message, it's message store private ConcurrentMap m_persistentMessageStore; - MapDBMessagesStore(DB db) { m_db = db; } @@ -83,10 +82,15 @@ class MapDBMessagesStore implements IMessagesStore { assert storedMessage.getClientID() != null : "The message to be persisted must have a valid client ID"; MessageGUID guid = new MessageGUID(UUID.randomUUID().toString()); storedMessage.setGuid(guid); - LOG.debug("Storing publish event. MqttClientId = {}, messageId = {}, guid = {}, topic = {}.", - storedMessage.getClientID(), storedMessage.getMessageID(), guid, storedMessage.getTopic()); + LOG.debug( + "Storing publish event. MqttClientId = {}, messageId = {}, guid = {}, topic = {}.", + storedMessage.getClientID(), + storedMessage.getMessageID(), + guid, + storedMessage.getTopic()); m_persistentMessageStore.put(guid, storedMessage); - ConcurrentMap messageIdToGuid = m_db.getHashMap(MapDBSessionsStore.messageId2GuidsMapName(storedMessage.getClientID())); + ConcurrentMap messageIdToGuid = m_db + .getHashMap(MapDBSessionsStore.messageId2GuidsMapName(storedMessage.getClientID())); messageIdToGuid.put(storedMessage.getMessageID(), guid); return guid; } @@ -94,7 +98,8 @@ class MapDBMessagesStore implements IMessagesStore { @Override public void dropMessagesInSession(String clientID) { LOG.debug("Dropping stored messages. ClientId = {}.", clientID); - ConcurrentMap messageIdToGuid = m_db.getHashMap(MapDBSessionsStore.messageId2GuidsMapName(clientID)); + ConcurrentMap messageIdToGuid = m_db + .getHashMap(MapDBSessionsStore.messageId2GuidsMapName(clientID)); for (MessageGUID guid : messageIdToGuid.values()) { removeStoredMessage(guid); } @@ -102,11 +107,15 @@ class MapDBMessagesStore implements IMessagesStore { } void removeStoredMessage(MessageGUID guid) { - //remove only the not retained and no more referenced + // remove only the not retained and no more referenced StoredMessage storedMessage = m_persistentMessageStore.get(guid); if (!storedMessage.isRetained()) { - LOG.debug("Dropping stored message. ClientId = {}, messageId = {}, guid = {}, topic = {}.", - storedMessage.getClientID(), storedMessage.getMessageID(), guid, storedMessage.getTopic()); + LOG.debug( + "Dropping stored message. ClientId = {}, messageId = {}, guid = {}, topic = {}.", + storedMessage.getClientID(), + storedMessage.getMessageID(), + guid, + storedMessage.getTopic()); m_persistentMessageStore.remove(guid); } } diff --git a/broker/src/main/java/io/moquette/spi/persistence/MapDBPersistentStore.java b/broker/src/main/java/io/moquette/spi/persistence/MapDBPersistentStore.java index d36ac919..801a1244 100644 --- a/broker/src/main/java/io/moquette/spi/persistence/MapDBPersistentStore.java +++ b/broker/src/main/java/io/moquette/spi/persistence/MapDBPersistentStore.java @@ -23,14 +23,12 @@ import org.mapdb.DB; import org.mapdb.DBMaker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.io.File; import java.io.IOException; import java.io.Serializable; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; - import static io.moquette.BrokerConstants.AUTOSAVE_INTERVAL_PROPERTY_NAME; import static io.moquette.BrokerConstants.PERSISTENT_STORE_PROPERTY_NAME; @@ -40,10 +38,11 @@ import static io.moquette.BrokerConstants.PERSISTENT_STORE_PROPERTY_NAME; public class MapDBPersistentStore { /** - * This is a DTO used to persist minimal status (clean session and activation status) of - * a session. - * */ + * This is a DTO used to persist minimal status (clean session and activation status) of a + * session. + */ public static class PersistentSession implements Serializable { + private static final long serialVersionUID = 5052054783220481854L; public final boolean cleanSession; @@ -69,8 +68,9 @@ public class MapDBPersistentStore { /** * Factory method to create message store backed by MapDB + * * @return the message store instance. - * */ + */ public IMessagesStore messagesStore() { return m_messageStore; } @@ -78,7 +78,7 @@ public class MapDBPersistentStore { public ISessionsStore sessionsStore() { return m_sessionsStore; } - + public void initStore() { LOG.info("Initializing MapDB store..."); if (m_storePath == null || m_storePath.isEmpty()) { @@ -92,13 +92,20 @@ public class MapDBPersistentStore { boolean fileNewlyCreated = tmpFile.createNewFile(); LOG.warn("Using {} MapDB store file. Path = {}.", fileNewlyCreated ? "fresh" : "existing", m_storePath); } catch (IOException ex) { - LOG.error("Unable to open MapDB store file. Path = {}, cause = {}, errorMessage = {}.", m_storePath, ex.getCause(), ex.getMessage()); - throw new RuntimeException("Can't create temp file for subscriptions storage [" + m_storePath + "]", ex); + LOG.error( + "Unable to open MapDB store file. Path = {}, cause = {}, errorMessage = {}.", + m_storePath, + ex.getCause(), + ex.getMessage()); + throw new RuntimeException( + "Can't create temp file for subscriptions storage [" + m_storePath + "]", + ex); } m_db = DBMaker.newFileDB(tmpFile).make(); } LOG.info("Scheduling MapDB commit task..."); m_scheduler.scheduleWithFixedDelay(new Runnable() { + @Override public void run() { LOG.debug("Committing to MapDB..."); @@ -106,7 +113,7 @@ public class MapDBPersistentStore { } }, this.m_autosaveInterval, this.m_autosaveInterval, TimeUnit.SECONDS); - //TODO check m_db is valid and + // TODO check m_db is valid and m_messageStore = new MapDBMessagesStore(m_db); m_messageStore.initStore(); @@ -127,7 +134,8 @@ public class MapDBPersistentStore { this.m_scheduler.shutdown(); try { m_scheduler.awaitTermination(10L, TimeUnit.SECONDS); - } catch (InterruptedException e) {} + } catch (InterruptedException e) { + } if (!m_scheduler.isTerminated()) { LOG.warn("Forcing shutdown of MapDB commit tasks..."); m_scheduler.shutdown(); diff --git a/broker/src/main/java/io/moquette/spi/persistence/MapDBSessionsStore.java b/broker/src/main/java/io/moquette/spi/persistence/MapDBSessionsStore.java index e4dbb922..a270da15 100644 --- a/broker/src/main/java/io/moquette/spi/persistence/MapDBSessionsStore.java +++ b/broker/src/main/java/io/moquette/spi/persistence/MapDBSessionsStore.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.persistence; import io.moquette.spi.ClientSession; @@ -25,7 +26,6 @@ import io.moquette.spi.persistence.MapDBPersistentStore.PersistentSession; import org.mapdb.DB; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.util.*; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; @@ -40,12 +40,12 @@ class MapDBSessionsStore implements ISessionsStore { private static final Logger LOG = LoggerFactory.getLogger(MapDBSessionsStore.class); - //maps clientID->[MessageId -> guid] + // maps clientID->[MessageId -> guid] private ConcurrentMap> m_inflightStore; - //map clientID <-> set of currently in flight packet identifiers + // map clientID <-> set of currently in flight packet identifiers private Map> m_inFlightIds; private ConcurrentMap m_persistentSessions; - //maps clientID->[MessageId -> guid] + // maps clientID->[MessageId -> guid] private ConcurrentMap> m_secondPhaseStore; private final DB m_db; @@ -66,14 +66,18 @@ class MapDBSessionsStore implements ISessionsStore { @Override public void addNewSubscription(Subscription newSubscription) { - LOG.info("Adding new subscription. CId= {}, topics = {}.", newSubscription.getClientId(), + LOG.info( + "Adding new subscription. CId= {}, topics = {}.", + newSubscription.getClientId(), newSubscription.getTopicFilter()); final String clientID = newSubscription.getClientId(); m_db.getHashMap("subscriptions_" + clientID).put(newSubscription.getTopicFilter(), newSubscription); if (LOG.isTraceEnabled()) { - LOG.trace("The subscription has been added. CId= {}, topics = {}, clientSubscriptions = {}.", - newSubscription.getClientId(), newSubscription.getTopicFilter(), + LOG.trace( + "The subscription has been added. CId= {}, topics = {}, clientSubscriptions = {}.", + newSubscription.getClientId(), + newSubscription.getTopicFilter(), m_db.getHashMap("subscriptions_" + clientID)); } } @@ -86,8 +90,11 @@ class MapDBSessionsStore implements ISessionsStore { } m_db.getHashMap("subscriptions_" + clientID).remove(topicFilter); if (LOG.isDebugEnabled()) { - LOG.debug("The subscription has been removed. CId= {}, topics = {}, clientSubscriptions = {}.", - clientID, topicFilter, m_db.getHashMap("subscriptions_" + clientID)); + LOG.debug( + "The subscription has been removed. CId= {}, topics = {}, clientSubscriptions = {}.", + clientID, + topicFilter, + m_db.getHashMap("subscriptions_" + clientID)); } } @@ -96,7 +103,9 @@ class MapDBSessionsStore implements ISessionsStore { LOG.info("Wiping subscriptions. CId= {}.", clientID); m_db.delete("subscriptions_" + clientID); if (LOG.isDebugEnabled()) { - LOG.debug("The subscriptions have been removed. CId= {}, clientSubscriptions = {}.", clientID, + LOG.debug( + "The subscriptions have been removed. CId= {}, clientSubscriptions = {}.", + clientID, m_db.getHashMap("subscriptions_" + clientID)); } } @@ -120,8 +129,7 @@ class MapDBSessionsStore implements ISessionsStore { @Override public Subscription getSubscription(ClientTopicCouple couple) { ConcurrentMap clientSubscriptions = m_db.getHashMap("subscriptions_" + couple.clientID); - LOG.info("Retrieving subscriptions. CId= {}, subscriptions = {}.", couple.clientID, - clientSubscriptions); + LOG.info("Retrieving subscriptions. CId= {}, subscriptions = {}.", couple.clientID, clientSubscriptions); return clientSubscriptions.get(couple.topicFilter); } @@ -147,7 +155,8 @@ class MapDBSessionsStore implements ISessionsStore { if (m_persistentSessions.containsKey(clientID)) { LOG.error( "Unable to create a new session: the client ID is already in use. CId= {}, cleanSession = {}.", - clientID, cleanSession); + clientID, + cleanSession); throw new IllegalArgumentException("Can't create a session with the ID of an already existing" + clientID); } LOG.info("Creating new session. CId= {}, cleanSession = {}.", clientID, cleanSession); @@ -166,10 +175,10 @@ class MapDBSessionsStore implements ISessionsStore { PersistentSession storedSession = m_persistentSessions.get(clientID); return new ClientSession(clientID, m_messagesStore, this, storedSession.cleanSession); } - + @Override public Collection getAllSessions() { - Collection result = new ArrayList(); + Collection result = new ArrayList<>(); for (Map.Entry entry : m_persistentSessions.entrySet()) { result.add(new ClientSession(entry.getKey(), m_messagesStore, this, entry.getValue().cleanSession)); } @@ -184,7 +193,7 @@ class MapDBSessionsStore implements ISessionsStore { /** * Return the next valid packetIdentifier for the given client session. - * */ + */ @Override public int nextPacketID(String clientID) { if (LOG.isDebugEnabled()) { @@ -219,7 +228,7 @@ class MapDBSessionsStore implements ISessionsStore { } m.remove(messageID); - //remove from the ids store + // remove from the ids store Set inFlightForClient = this.m_inFlightIds.get(clientID); if (inFlightForClient != null) { inFlightForClient.remove(messageID); @@ -262,13 +271,14 @@ class MapDBSessionsStore implements ISessionsStore { } MessageGUID guid = m.remove(messageID); - //remove from the ids store + // remove from the ids store Set inFlightForClient = this.m_inFlightIds.get(clientID); if (inFlightForClient != null) { inFlightForClient.remove(messageID); } - Map messageIDs = Utils.defaultGet(m_secondPhaseStore, clientID, new HashMap()); + Map messageIDs = Utils + .defaultGet(m_secondPhaseStore, clientID, new HashMap()); messageIDs.put(messageID, guid); m_secondPhaseStore.put(clientID, messageIDs); } @@ -278,7 +288,8 @@ class MapDBSessionsStore implements ISessionsStore { if (LOG.isDebugEnabled()) { LOG.debug("Processing second phase ACK CId={}, messageId={}", clientID, messageID); } - Map messageIDs = Utils.defaultGet(m_secondPhaseStore, clientID, new HashMap()); + Map messageIDs = Utils + .defaultGet(m_secondPhaseStore, clientID, new HashMap()); MessageGUID guid = messageIDs.remove(messageID); m_secondPhaseStore.put(clientID, messageIDs); return guid; @@ -297,22 +308,21 @@ class MapDBSessionsStore implements ISessionsStore { return "guidsMapping_" + clientID; } - @Override - public StoredMessage getInflightMessage(String clientID, int messageID) { + @Override + public StoredMessage getInflightMessage(String clientID, int messageID) { LOG.info("Retrieving inflight message CId={}, messageId={}", clientID, messageID); - Map clientEntries = m_inflightStore.get(clientID); + Map clientEntries = m_inflightStore.get(clientID); if (clientEntries == null) { LOG.warn("The client has no inflight messages CId={}, messageId={}", clientID, messageID); return null; } MessageGUID guid = clientEntries.get(messageID); if (guid == null) { - LOG.warn("The message ID does not have an associated GUID. CId= {}, messageId = {}.", clientID, - messageID); + LOG.warn("The message ID does not have an associated GUID. CId= {}, messageId = {}.", clientID, messageID); return null; } - return m_messagesStore.getMessageByGuid(guid); - } + return m_messagesStore.getMessageByGuid(guid); + } @Override public int getInflightMessagesNo(String clientID) { diff --git a/broker/src/main/java/io/moquette/spi/security/IAuthenticator.java b/broker/src/main/java/io/moquette/spi/security/IAuthenticator.java index 8dee04b2..8df8a090 100644 --- a/broker/src/main/java/io/moquette/spi/security/IAuthenticator.java +++ b/broker/src/main/java/io/moquette/spi/security/IAuthenticator.java @@ -13,11 +13,12 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.security; /** * username and password checker - * + * * @author andrea */ public interface IAuthenticator { diff --git a/broker/src/main/java/io/moquette/spi/security/IAuthorizator.java b/broker/src/main/java/io/moquette/spi/security/IAuthorizator.java index 3d85c1b8..cba7ab5f 100644 --- a/broker/src/main/java/io/moquette/spi/security/IAuthorizator.java +++ b/broker/src/main/java/io/moquette/spi/security/IAuthorizator.java @@ -13,14 +13,14 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.security; /** * ACL checker. * - * Create an authorizator that matches topic names with same grammar of subscriptions. - * The # is always a terminator and its the multilevel matcher. - * The + sign is the single level matcher. + * Create an authorizator that matches topic names with same grammar of subscriptions. The # is + * always a terminator and its the multilevel matcher. The + sign is the single level matcher. * * @author andrea */ @@ -28,11 +28,15 @@ public interface IAuthorizator { /** * Ask the implementation of the authorizator if the topic can be used in a publish. - * @param topic the topic to write to. - * @param user the user - * @param client the client + * + * @param topic + * the topic to write to. + * @param user + * the user + * @param client + * the client * @return true if the user from client can publish data on topic. - * */ + */ boolean canWrite(String topic, String user, String client); boolean canRead(String topic, String user, String client); diff --git a/broker/src/main/java/io/moquette/spi/security/ISslContextCreator.java b/broker/src/main/java/io/moquette/spi/security/ISslContextCreator.java index 34863e2d..0466a41d 100644 --- a/broker/src/main/java/io/moquette/spi/security/ISslContextCreator.java +++ b/broker/src/main/java/io/moquette/spi/security/ISslContextCreator.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.security; import javax.net.ssl.SSLContext; diff --git a/broker/src/test/java/io/moquette/Utils.java b/broker/src/test/java/io/moquette/Utils.java index bf37fa65..08aedbad 100644 --- a/broker/src/test/java/io/moquette/Utils.java +++ b/broker/src/test/java/io/moquette/Utils.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette; import io.netty.buffer.ByteBuf; @@ -23,7 +24,6 @@ import io.netty.util.Attribute; import io.netty.util.AttributeKey; import io.netty.util.AttributeMap; import org.slf4j.LoggerFactory; - import java.io.UnsupportedEncodingException; /** @@ -31,44 +31,43 @@ import java.io.UnsupportedEncodingException; * @author andrea */ public class Utils { - + public static final int MAX_LENGTH_LIMIT = 268435455; - + public static final byte VERSION_3_1 = 3; public static final byte VERSION_3_1_1 = 4; - + static byte readMessageType(ByteBuf in) { byte h1 = in.readByte(); byte messageType = (byte) ((h1 & 0x00F0) >> 4); return messageType; } - + static boolean checkHeaderAvailability(ByteBuf in) { if (in.readableBytes() < 1) { return false; } - //byte h1 = in.get(); - //byte messageType = (byte) ((h1 & 0x00F0) >> 4); - in.skipBytes(1); //skip the messageType byte - + // byte h1 = in.get(); + // byte messageType = (byte) ((h1 & 0x00F0) >> 4); + in.skipBytes(1); // skip the messageType byte + int remainingLength = Utils.decodeRemainingLenght(in); if (remainingLength == -1) { return false; } - - //check remaining length + + // check remaining length if (in.readableBytes() < remainingLength) { return false; } - - //return messageType == type ? MessageDecoderResult.OK : MessageDecoderResult.NOT_OK; + + // return messageType == type ? MessageDecoderResult.OK : MessageDecoderResult.NOT_OK; return true; } - + /** - * Decode the variable remaining length as defined in MQTT v3.1 specification - * (section 2.1). - * + * Decode the variable remaining length as defined in MQTT v3.1 specification (section 2.1). + * * @return the decoded length or -1 if needed more data to decode the length field. */ static int decodeRemainingLenght(ByteBuf in) { @@ -85,13 +84,12 @@ public class Utils { } while ((digit & 0x80) != 0); return value; } - + /** - * Encode the value in the format defined in specification as variable length - * array. - * - * @throws IllegalArgumentException if the value is not in the specification bounds - * [0..268435455]. + * Encode the value in the format defined in specification as variable length array. + * + * @throws IllegalArgumentException + * if the value is not in the specification bounds [0..268435455]. */ static ByteBuf encodeRemainingLength(int value) throws CorruptedFrameException { if (value > MAX_LENGTH_LIMIT || value < 0) { @@ -111,11 +109,11 @@ public class Utils { } while (value > 0); return encoded; } - + /** - * Load a string from the given buffer, reading first the two bytes of len - * and then the UTF-8 bytes of the string. - * + * Load a string from the given buffer, reading first the two bytes of len and then the UTF-8 + * bytes of the string. + * * @return the decoded string or null if NEED_DATA */ static String decodeString(ByteBuf in) throws UnsupportedEncodingException { @@ -123,8 +121,9 @@ public class Utils { } /** - * Read a byte array from the buffer, use two bytes as length information followed by length bytes. - * */ + * Read a byte array from the buffer, use two bytes as length information followed by length + * bytes. + */ static byte[] readFixedLengthContent(ByteBuf in) throws UnsupportedEncodingException { if (in.readableBytes() < 2) { return null; @@ -140,15 +139,14 @@ public class Utils { } /** - * Return the IoBuffer with string encoded as MSB, LSB and UTF-8 encoded - * string content. + * Return the IoBuffer with string encoded as MSB, LSB and UTF-8 encoded string content. */ public static ByteBuf encodeString(String str) { byte[] raw; try { raw = str.getBytes("UTF-8"); - //NB every Java platform has got UTF-8 encoding by default, so this - //exception are never raised. + // NB every Java platform has got UTF-8 encoding by default, so this + // exception are never raised. } catch (UnsupportedEncodingException ex) { LoggerFactory.getLogger(Utils.class).error(null, ex); return null; @@ -170,13 +168,17 @@ public class Utils { * Return the number of bytes to encode the given remaining length value */ static int numBytesToEncode(int len) { - if (0 <= len && len <= 127) return 1; - if (128 <= len && len <= 16383) return 2; - if (16384 <= len && len <= 2097151) return 3; - if (2097152 <= len && len <= 268435455) return 4; + if (0 <= len && len <= 127) + return 1; + if (128 <= len && len <= 16383) + return 2; + if (16384 <= len && len <= 2097151) + return 3; + if (2097152 <= len && len <= 268435455) + return 4; throw new IllegalArgumentException("value shoul be in the range [0..268435455]"); } - + static byte encodeFlags(MqttMessage message) { byte flags = 0; if (message.fixedHeader().isDup()) { @@ -185,20 +187,20 @@ public class Utils { if (message.fixedHeader().isRetain()) { flags |= 0x01; } - + flags |= ((message.fixedHeader().qosLevel().value() & 0x03) << 1); return flags; } - //3 = 3.1, 4 = 3.1.1 -// static final AttributeKey PROTOCOL_VERSION = AttributeKey.valueOf("version"); -// -// static boolean isMQTT3_1_1(AttributeMap attrsMap) { -// Attribute versionAttr = attrsMap.attr(PROTOCOL_VERSION); -// Integer protocolVersion = versionAttr.get(); -// if (protocolVersion == null) { -// return true; -// } -// return protocolVersion == VERSION_3_1_1; -// } + // 3 = 3.1, 4 = 3.1.1 + // static final AttributeKey PROTOCOL_VERSION = AttributeKey.valueOf("version"); + // + // static boolean isMQTT3_1_1(AttributeMap attrsMap) { + // Attribute versionAttr = attrsMap.attr(PROTOCOL_VERSION); + // Integer protocolVersion = versionAttr.get(); + // if (protocolVersion == null) { + // return true; + // } + // return protocolVersion == VERSION_3_1_1; + // } } diff --git a/broker/src/test/java/io/moquette/server/ConfigurationClassLoaderTest.java b/broker/src/test/java/io/moquette/server/ConfigurationClassLoaderTest.java index ab1f87f5..6eb6ea7f 100644 --- a/broker/src/test/java/io/moquette/server/ConfigurationClassLoaderTest.java +++ b/broker/src/test/java/io/moquette/server/ConfigurationClassLoaderTest.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server; import io.moquette.BrokerConstants; @@ -22,33 +23,31 @@ import io.moquette.spi.security.IAuthenticator; import io.moquette.spi.security.IAuthorizator; import org.junit.After; import org.junit.Test; - import java.io.File; import java.io.IOException; import java.util.Properties; - import static org.junit.Assert.*; /** * - * @author luca + * @author luca */ public class ConfigurationClassLoaderTest implements IAuthenticator, IAuthorizator { + Server m_server; IConfig m_config; - + protected void startServer(Properties props) throws IOException { m_server = new Server(); m_config = new MemoryConfig(props); m_server.startServer(m_config); } - @After public void tearDown() throws Exception { m_server.stopServer(); } - + @Test public void loadAuthenticator() throws Exception { Properties props = new Properties(IntegrationUtils.prepareTestProperties()); @@ -56,7 +55,7 @@ public class ConfigurationClassLoaderTest implements IAuthenticator, IAuthorizat startServer(props); assertTrue(true); } - + @Test public void loadAuthorizator() throws Exception { Properties props = new Properties(IntegrationUtils.prepareTestProperties()); @@ -79,5 +78,5 @@ public class ConfigurationClassLoaderTest implements IAuthenticator, IAuthorizat public boolean canRead(String topic, String user, String client) { return true; } - + } diff --git a/broker/src/test/java/io/moquette/server/IntegrationUtils.java b/broker/src/test/java/io/moquette/server/IntegrationUtils.java index 7b9696cf..3fedd569 100644 --- a/broker/src/test/java/io/moquette/server/IntegrationUtils.java +++ b/broker/src/test/java/io/moquette/server/IntegrationUtils.java @@ -13,13 +13,12 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server; import io.moquette.server.config.IConfig; - import java.io.File; import java.util.Properties; - import static io.moquette.BrokerConstants.DEFAULT_MOQUETTE_STORE_MAP_DB_FILENAME; import static io.moquette.BrokerConstants.PERSISTENT_STORE_PROPERTY_NAME; import static io.moquette.BrokerConstants.PORT_PROPERTY_NAME; @@ -31,6 +30,7 @@ import static org.junit.Assert.assertFalse; * Created by andrea on 4/7/15. */ public class IntegrationUtils { + static String localMapDBPath() { String currentDir = System.getProperty("user.dir"); return currentDir + File.separator + DEFAULT_MOQUETTE_STORE_MAP_DB_FILENAME; diff --git a/broker/src/test/java/io/moquette/server/MQTTWebSocket.java b/broker/src/test/java/io/moquette/server/MQTTWebSocket.java index acdbd905..06b89708 100644 --- a/broker/src/test/java/io/moquette/server/MQTTWebSocket.java +++ b/broker/src/test/java/io/moquette/server/MQTTWebSocket.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server; import java.io.IOException; @@ -35,62 +36,61 @@ import org.slf4j.LoggerFactory; */ @WebSocket public class MQTTWebSocket { - + private static final Logger LOG = LoggerFactory.getLogger(MQTTWebSocket.class); - + private Session session; - + private final CountDownLatch connectSentLatch; - + public MQTTWebSocket() { this.connectSentLatch = new CountDownLatch(1); } - + @OnWebSocketClose public void onClose(int statusCode, String reason) { System.out.printf("Connection closed: %d - %s%n", statusCode, reason); this.session = null; } - + @OnWebSocketConnect public void onConnect(Session session) throws IOException { System.out.printf("Got connect: %s%n", session); LOG.info("Got connect: %s%n", session); this.session = session; - - //Trivial MQTT Connect message -// assertEquals(12, out.readByte()); //remaining length -// verifyString("MQIsdp", out); -// assertEquals(0x03, out.readByte()); //protocol version -// assertEquals(0x32, out.readByte()); //flags -// assertEquals(2, out.readByte()); //keepAliveTimer msb -// assertEquals(0, out.readByte()); //keepAliveTimer lsb - - ByteBuffer msg = ByteBuffer.wrap(new byte[] { 0x10, //message type - 0x0C, //remaining lenght 12 bytes - 'M', 'Q','I','s','d','p', - 0x03, //protocol version - 0x32, //flags - 0x02, 0x00// keepAlive Timer, 2 seconds + + // Trivial MQTT Connect message + // assertEquals(12, out.readByte()); //remaining length + // verifyString("MQIsdp", out); + // assertEquals(0x03, out.readByte()); //protocol version + // assertEquals(0x32, out.readByte()); //flags + // assertEquals(2, out.readByte()); //keepAliveTimer msb + // assertEquals(0, out.readByte()); //keepAliveTimer lsb + + ByteBuffer msg = ByteBuffer.wrap(new byte[]{0x10, // message type + 0x0C, // remaining lenght 12 bytes + 'M', 'Q', 'I', 's', 'd', 'p', 0x03, // protocol version + 0x32, // flags + 0x02, 0x00// keepAlive Timer, 2 seconds }); -// try { - session.getRemote().sendBytes(msg); - this.connectSentLatch.countDown(); - session.close(StatusCode.NORMAL, "I'm done"); -// } catch (IOException t) { -// LOG.error(null, t); -// } + // try { + session.getRemote().sendBytes(msg); + this.connectSentLatch.countDown(); + session.close(StatusCode.NORMAL, "I'm done"); + // } catch (IOException t) { + // LOG.error(null, t); + // } } - + public boolean awaitConnected(int duration, TimeUnit unit) throws InterruptedException { return this.connectSentLatch.await(duration, unit); } - + @OnWebSocketMessage public void onMessage(Session session, byte[] buf, int offset, int length) { System.out.printf("Got msg: %s%n", buf); } - + @OnWebSocketError public void onError(Session session, Throwable cause) { System.out.printf("Got exception: %s%n", cause); diff --git a/broker/src/test/java/io/moquette/server/MessageCollector.java b/broker/src/test/java/io/moquette/server/MessageCollector.java index 74d5f664..07cf40be 100644 --- a/broker/src/test/java/io/moquette/server/MessageCollector.java +++ b/broker/src/test/java/io/moquette/server/MessageCollector.java @@ -13,12 +13,12 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server; import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; import org.eclipse.paho.client.mqttv3.MqttCallback; import org.eclipse.paho.client.mqttv3.MqttMessage; - import java.util.concurrent.*; /** @@ -27,6 +27,7 @@ import java.util.concurrent.*; public class MessageCollector implements MqttCallback { private class ReceivedMessage { + private final MqttMessage message; private final String topic; @@ -41,7 +42,7 @@ public class MessageCollector implements MqttCallback { /** * Return the message from the queue if not empty, else return null with wait period. - * */ + */ public MqttMessage getMessageImmediate() { if (m_messages.isEmpty()) { return null; @@ -94,13 +95,13 @@ public class MessageCollector implements MqttCallback { /** * Invoked when the message sent to a server is ACKED (PUBACK or PUBCOMP by the server) - * */ + */ @Override public void deliveryComplete(IMqttDeliveryToken token) { -// try { -// m_messages.offer(new ReceivedMessage(token.waitMessage(), token.getTopics()[0])); -// } catch (MqttException e) { -// e.printStackTrace(); -// } + // try { + // m_messages.offer(new ReceivedMessage(token.waitMessage(), token.getTopics()[0])); + // } catch (MqttException e) { + // e.printStackTrace(); + // } } } diff --git a/broker/src/test/java/io/moquette/server/ServerIntegrationDBAuthenticatorTest.java b/broker/src/test/java/io/moquette/server/ServerIntegrationDBAuthenticatorTest.java index d27ebb33..1e23b545 100644 --- a/broker/src/test/java/io/moquette/server/ServerIntegrationDBAuthenticatorTest.java +++ b/broker/src/test/java/io/moquette/server/ServerIntegrationDBAuthenticatorTest.java @@ -1,3 +1,4 @@ + package io.moquette.server; import io.moquette.BrokerConstants; @@ -10,19 +11,18 @@ import org.eclipse.paho.client.mqttv3.persist.MqttDefaultFilePersistence; import org.junit.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.io.File; import java.io.IOException; import java.security.NoSuchAlgorithmException; import java.sql.SQLException; import java.util.Properties; - import static org.junit.Assert.assertTrue; /** * Created by mackristof on 13/05/2016. */ public class ServerIntegrationDBAuthenticatorTest { + private static final Logger LOG = LoggerFactory.getLogger(ServerIntegrationDBAuthenticatorTest.class); static MqttClientPersistence s_dataStore; @@ -35,8 +35,6 @@ public class ServerIntegrationDBAuthenticatorTest { MessageCollector m_messagesCollector; IConfig m_config; - - @BeforeClass public static void beforeTests() throws NoSuchAlgorithmException, SQLException, ClassNotFoundException { String tmpDir = System.getProperty("java.io.tmpdir"); @@ -53,7 +51,6 @@ public class ServerIntegrationDBAuthenticatorTest { m_server.startServer(m_config); } - private void stopServer() { m_server.stopServer(); IntegrationUtils.cleanPersistenceFile(m_config); @@ -96,7 +93,7 @@ public class ServerIntegrationDBAuthenticatorTest { } @AfterClass - public static void shutdown(){ + public static void shutdown() { dbAuthenticatorTest.teardown(); } @@ -111,9 +108,8 @@ public class ServerIntegrationDBAuthenticatorTest { assertTrue(true); } - @Test - public void connectWithWrongCredentials() { + public void connectWithWrongCredentials() { LOG.info("*** connectWithWrongCredentials ***"); try { m_client = new MqttClient("tcp://localhost:1883", "Publisher", s_pubDataStore); @@ -121,18 +117,16 @@ public class ServerIntegrationDBAuthenticatorTest { options.setUserName("dbuser"); options.setPassword("wrongPassword".toCharArray()); m_client.connect(options); - } catch (MqttException e){ + } catch (MqttException e) { if (e instanceof MqttSecurityException) { assertTrue(true); return; } else { - assertTrue(e.getMessage(),false); + assertTrue(e.getMessage(), false); return; } } - assertTrue("must not be connected. cause : wrong password given to client",false); - + assertTrue("must not be connected. cause : wrong password given to client", false); } - } diff --git a/broker/src/test/java/io/moquette/server/ServerIntegrationEmbeddedPublishTest.java b/broker/src/test/java/io/moquette/server/ServerIntegrationEmbeddedPublishTest.java index 9af07ccf..a83e75d3 100644 --- a/broker/src/test/java/io/moquette/server/ServerIntegrationEmbeddedPublishTest.java +++ b/broker/src/test/java/io/moquette/server/ServerIntegrationEmbeddedPublishTest.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server; import io.moquette.server.netty.MessageBuilder; @@ -28,11 +29,9 @@ import org.junit.BeforeClass; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.io.File; import java.io.IOException; import java.util.Properties; - import static org.junit.Assert.*; public class ServerIntegrationEmbeddedPublishTest { @@ -89,12 +88,8 @@ public class ServerIntegrationEmbeddedPublishTest { } private void internalPublishToWithQosAndRetained(String topic, MqttQoS qos, boolean retained) { - MqttPublishMessage message = MessageBuilder.publish() - .topicName(topic) - .retained(retained) - .qos(qos) - .payload("Hello world MQTT!!".getBytes()) - .build(); + MqttPublishMessage message = MessageBuilder.publish().topicName(topic).retained(retained).qos(qos) + .payload("Hello world MQTT!!".getBytes()).build(); m_server.internalPublish(message, "INTRPUBL"); } @@ -115,7 +110,7 @@ public class ServerIntegrationEmbeddedPublishTest { } private void verifyMessageIsReceivedSuccessfully() throws Exception { - //check in 2 seconds + // check in 2 seconds MqttMessage msg = m_callback.waitMessage(2); assertNotNull(msg); assertEquals("Hello world MQTT!!", new String(msg.getPayload())); @@ -125,11 +120,11 @@ public class ServerIntegrationEmbeddedPublishTest { public void testClientSubscribeAfterNotRetainedQoS0IsSent() throws Exception { LOG.info("*** testClientSubscribeAfterNotRetainedQoS0IsSent ***"); - //Exercise + // Exercise internalPublishToWithQosAndRetained("/topic", MqttQoS.AT_MOST_ONCE, false); subscribeToWithQos("/topic", 0); - //Verify + // Verify verifyNoMessageIsReceived(); } @@ -139,10 +134,10 @@ public class ServerIntegrationEmbeddedPublishTest { subscribeToWithQos("/topic", 0); - //Exercise + // Exercise internalPublishToWithQosAndRetained("/topic", MqttQoS.AT_MOST_ONCE, false); - //Verify + // Verify verifyMessageIsReceivedSuccessfully(); } @@ -152,10 +147,10 @@ public class ServerIntegrationEmbeddedPublishTest { subscribeToWithQos("/topic", 0); - //Exercise + // Exercise internalPublishToWithQosAndRetained("/topic", MqttQoS.AT_MOST_ONCE, true); - //Verify + // Verify verifyMessageIsReceivedSuccessfully(); } @@ -163,12 +158,12 @@ public class ServerIntegrationEmbeddedPublishTest { public void testClientSubscribeAfterRetainedQoS0IsSent() throws Exception { LOG.info("*** testClientSubscribeAfterRetainedQoS0IsSent ***"); - //Exercise + // Exercise internalPublishToWithQosAndRetained("/topic", MqttQoS.AT_MOST_ONCE, true); - //LOG.info("** post internalPublish **"); + // LOG.info("** post internalPublish **"); subscribeToWithQos("/topic", 0); - //Verify + // Verify verifyNoMessageIsReceived(); } @@ -178,10 +173,10 @@ public class ServerIntegrationEmbeddedPublishTest { subscribeToWithQos("/topic", 1); - //Exercise + // Exercise internalPublishToWithQosAndRetained("/topic", MqttQoS.AT_LEAST_ONCE, false); - //Verify + // Verify verifyMessageIsReceivedSuccessfully(); } @@ -189,11 +184,11 @@ public class ServerIntegrationEmbeddedPublishTest { public void testClientSubscribeAfterNotRetainedQoS1IsSent() throws Exception { LOG.info("*** testClientSubscribeAfterNotRetainedQoS1IsSent ***"); - //Exercise + // Exercise internalPublishToWithQosAndRetained("/topic", MqttQoS.AT_LEAST_ONCE, false); subscribeToWithQos("/topic", 1); - //Verify + // Verify verifyNoMessageIsReceived(); } @@ -203,10 +198,10 @@ public class ServerIntegrationEmbeddedPublishTest { subscribeToWithQos("/topic", 1); - //Exercise + // Exercise internalPublishToWithQosAndRetained("/topic", MqttQoS.AT_LEAST_ONCE, true); - //Verify + // Verify verifyMessageIsReceivedSuccessfully(); } @@ -214,12 +209,12 @@ public class ServerIntegrationEmbeddedPublishTest { public void testClientSubscribeAfterRetainedQoS1IsSent() throws Exception { LOG.info("*** testClientSubscribeAfterRetainedQoS0IsSent ***"); - //Exercise + // Exercise internalPublishToWithQosAndRetained("/topic", MqttQoS.AT_LEAST_ONCE, true); subscribeToWithQos("/topic", MqttQoS.AT_LEAST_ONCE.value()); LOG.info("** After subscribe **"); - //Verify + // Verify verifyMessageIsReceivedSuccessfully(); LOG.info("** Post verify **"); } @@ -230,10 +225,10 @@ public class ServerIntegrationEmbeddedPublishTest { subscribeToWithQos("/topic", 2); - //Exercise + // Exercise internalPublishToWithQosAndRetained("/topic", MqttQoS.EXACTLY_ONCE, false); - //Verify + // Verify verifyMessageIsReceivedSuccessfully(); } @@ -241,11 +236,11 @@ public class ServerIntegrationEmbeddedPublishTest { public void testClientSubscribeAfterNotRetainedQoS2IsSent() throws Exception { LOG.info("*** testClientSubscribeAfterNotRetainedQoS2IsSent ***"); - //Exercise + // Exercise internalPublishToWithQosAndRetained("/topic", MqttQoS.EXACTLY_ONCE, false); subscribeToWithQos("/topic", 2); - //Verify + // Verify verifyNoMessageIsReceived(); } @@ -255,10 +250,10 @@ public class ServerIntegrationEmbeddedPublishTest { subscribeToWithQos("/topic", 2); - //Exercise + // Exercise internalPublishToWithQosAndRetained("/topic", MqttQoS.EXACTLY_ONCE, true); - //Verify + // Verify verifyMessageIsReceivedSuccessfully(); } @@ -266,11 +261,11 @@ public class ServerIntegrationEmbeddedPublishTest { public void testClientSubscribeAfterRetainedQoS2IsSent() throws Exception { LOG.info("*** testClientSubscribeAfterRetainedQoS2IsSent ***"); - //Exercise + // Exercise internalPublishToWithQosAndRetained("/topic", MqttQoS.EXACTLY_ONCE, true); subscribeToWithQos("/topic", 2); - //Verify + // Verify verifyMessageIsReceivedSuccessfully(); } @@ -283,8 +278,8 @@ public class ServerIntegrationEmbeddedPublishTest { internalPublishToWithQosAndRetained("foo", MqttQoS.AT_MOST_ONCE, false); - //verifyMessageIsReceivedSuccessfully(); - //m_subscriber.receive(2, TimeUnit.MILLISECONDS); + // verifyMessageIsReceivedSuccessfully(); + // m_subscriber.receive(2, TimeUnit.MILLISECONDS); MqttMessage message = m_callback.waitMessage(1); assertTrue(message == null); } diff --git a/broker/src/test/java/io/moquette/server/ServerIntegrationFuseTest.java b/broker/src/test/java/io/moquette/server/ServerIntegrationFuseTest.java index d2be487a..ed936b54 100644 --- a/broker/src/test/java/io/moquette/server/ServerIntegrationFuseTest.java +++ b/broker/src/test/java/io/moquette/server/ServerIntegrationFuseTest.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server; import io.moquette.server.config.IConfig; @@ -23,11 +24,9 @@ import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.io.IOException; import java.util.Properties; import java.util.concurrent.TimeUnit; - import static org.junit.Assert.*; /** @@ -35,6 +34,7 @@ import static org.junit.Assert.*; * @author andrea */ public class ServerIntegrationFuseTest { + private static final Logger LOG = LoggerFactory.getLogger(ServerIntegrationPahoTest.class); Server m_server; @@ -42,7 +42,7 @@ public class ServerIntegrationFuseTest { BlockingConnection m_subscriber; BlockingConnection m_publisher; IConfig m_config; - + protected void startServer() throws IOException { m_server = new Server(); final Properties configProps = IntegrationUtils.prepareTestProperties(); @@ -63,7 +63,7 @@ public class ServerIntegrationFuseTest { if (m_subscriber != null) { m_subscriber.disconnect(); } - + if (m_publisher != null) { m_publisher.disconnect(); } @@ -75,31 +75,31 @@ public class ServerIntegrationFuseTest { @Test public void checkWillTestamentIsPublishedOnConnectionKill_noRetain() throws Exception { LOG.info("checkWillTestamentIsPublishedOnConnectionKill_noRetain"); - + String willTestamentTopic = "/will/test"; String willTestamentMsg = "Bye bye"; - + MQTT mqtt = new MQTT(); - mqtt.setHost("localhost", 1883); + mqtt.setHost("localhost", 1883); mqtt.setClientId("WillTestamentPublisher"); mqtt.setWillRetain(false); mqtt.setWillMessage(willTestamentMsg); mqtt.setWillTopic(willTestamentTopic); m_publisher = mqtt.blockingConnection(); m_publisher.connect(); - - m_mqtt.setHost("localhost", 1883); + + m_mqtt.setHost("localhost", 1883); m_mqtt.setCleanSession(false); m_mqtt.setClientId("Subscriber"); m_subscriber = m_mqtt.blockingConnection(); m_subscriber.connect(); Topic[] topics = new Topic[]{new Topic(willTestamentTopic, QoS.AT_MOST_ONCE)}; m_subscriber.subscribe(topics); - - //Exercise, kill the publisher connection + + // Exercise, kill the publisher connection m_publisher.kill(); - - //Verify, that the testament is fired + + // Verify, that the testament is fired Message msg = m_subscriber.receive(500, TimeUnit.MILLISECONDS); assertNotNull("We should get notified with 'Will' message", msg); msg.ack(); diff --git a/broker/src/test/java/io/moquette/server/ServerIntegrationHazelcastHandlerInterceptorTest.java b/broker/src/test/java/io/moquette/server/ServerIntegrationHazelcastHandlerInterceptorTest.java index f1df9f2e..c156b92a 100644 --- a/broker/src/test/java/io/moquette/server/ServerIntegrationHazelcastHandlerInterceptorTest.java +++ b/broker/src/test/java/io/moquette/server/ServerIntegrationHazelcastHandlerInterceptorTest.java @@ -1,3 +1,4 @@ + package io.moquette.server; import io.moquette.BrokerConstants; @@ -12,16 +13,15 @@ import org.eclipse.paho.client.mqttv3.persist.MqttDefaultFilePersistence; import org.junit.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.io.File; import java.io.IOException; import java.security.NoSuchAlgorithmException; import java.sql.SQLException; import java.util.Properties; - import static org.junit.Assert.assertEquals; -public class ServerIntegrationHazelcastHandlerInterceptorTest{ +public class ServerIntegrationHazelcastHandlerInterceptorTest { + private static final Logger LOG = LoggerFactory.getLogger(ServerIntegrationHazelcastHandlerInterceptorTest.class); static MqttClientPersistence s_dataStore; @@ -55,7 +55,9 @@ public class ServerIntegrationHazelcastHandlerInterceptorTest{ private Properties addHazelCastConf(Properties properties, int port, String hazelcastConfigurationFile) { properties.put(BrokerConstants.PORT_PROPERTY_NAME, port); - properties.put(BrokerConstants.INTERCEPT_HANDLER_PROPERTY_NAME, HazelcastInterceptHandler.class.getCanonicalName()); + properties.put( + BrokerConstants.INTERCEPT_HANDLER_PROPERTY_NAME, + HazelcastInterceptHandler.class.getCanonicalName()); properties.put(BrokerConstants.HAZELCAST_CONFIGURATION, hazelcastConfigurationFile); return properties; } @@ -65,14 +67,18 @@ public class ServerIntegrationHazelcastHandlerInterceptorTest{ String dbPath = IntegrationUtils.localMapDBPath(); IntegrationUtils.cleanPersistenceFile(dbPath); - final Properties configProps = addHazelCastConf(IntegrationUtils.prepareTestClusterProperties(1883), - 1883, "config/hazelcast.xml"); + final Properties configProps = addHazelCastConf( + IntegrationUtils.prepareTestClusterProperties(1883), + 1883, + "config/hazelcast.xml"); m_config_1883 = new MemoryConfig(configProps); server1883 = startServer(1883, m_config_1883); - final Properties configProps1884 = addHazelCastConf(IntegrationUtils.prepareTestClusterProperties(1884), - 1883, "config/hazelcast.xml"); + final Properties configProps1884 = addHazelCastConf( + IntegrationUtils.prepareTestClusterProperties(1884), + 1883, + "config/hazelcast.xml"); m_config_1884 = new MemoryConfig(configProps1884); server1884 = startServer(1884, m_config_1884); diff --git a/broker/src/test/java/io/moquette/server/ServerIntegrationPahoTest.java b/broker/src/test/java/io/moquette/server/ServerIntegrationPahoTest.java index fe81c39a..0c0421fa 100644 --- a/broker/src/test/java/io/moquette/server/ServerIntegrationPahoTest.java +++ b/broker/src/test/java/io/moquette/server/ServerIntegrationPahoTest.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server; import io.moquette.server.config.IConfig; @@ -22,11 +23,9 @@ import org.eclipse.paho.client.mqttv3.persist.MqttDefaultFilePersistence; import org.junit.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.io.File; import java.io.IOException; import java.util.Properties; - import static org.junit.Assert.*; public class ServerIntegrationPahoTest { @@ -35,7 +34,7 @@ public class ServerIntegrationPahoTest { static MqttClientPersistence s_dataStore; static MqttClientPersistence s_pubDataStore; - + Server m_server; IMqttClient m_client; IMqttClient m_publisher; @@ -113,7 +112,6 @@ public class ServerIntegrationPahoTest { assertEquals("/topic", m_messagesCollector.getTopic()); } - @Test public void testCleanSession_maintainClientSubscriptions() throws Exception { @@ -124,7 +122,7 @@ public class ServerIntegrationPahoTest { m_client.subscribe("/topic", 0); m_client.disconnect(); - //reconnect and publish + // reconnect and publish MqttClient anotherClient = new MqttClient("tcp://localhost:1883", "TestClient", s_dataStore); m_messagesCollector = new MessageCollector(); anotherClient.setCallback(m_messagesCollector); @@ -134,7 +132,6 @@ public class ServerIntegrationPahoTest { assertEquals("/topic", m_messagesCollector.getTopic()); } - @Test public void testCleanSession_maintainClientSubscriptions_againstClientDestruction() throws Exception { LOG.info("*** testCleanSession_maintainClientSubscriptions_againstClientDestruction ***"); @@ -144,7 +141,7 @@ public class ServerIntegrationPahoTest { m_client.subscribe("/topic", 0); m_client.disconnect(); - //reconnect and publish + // reconnect and publish m_client.connect(options); m_client.publish("/topic", "Test my payload".getBytes(), 0, false); @@ -152,9 +149,9 @@ public class ServerIntegrationPahoTest { } /** - * Check that after a client has connected with clean session false, subscribed - * to some topic and exited, if it reconnects with clean session true, the m_server - * correctly cleanup every previous subscription + * Check that after a client has connected with clean session false, subscribed to some topic + * and exited, if it reconnects with clean session true, the m_server correctly cleanup every + * previous subscription */ @Test public void testCleanSession_correctlyClientSubscriptions() throws Exception { @@ -165,17 +162,17 @@ public class ServerIntegrationPahoTest { m_client.subscribe("/topic", 0); m_client.disconnect(); - //reconnect and publish - //options.setCleanSession(false); + // reconnect and publish + // options.setCleanSession(false); m_client = new MqttClient("tcp://localhost:1883", "TestClient", s_dataStore); MessageCollector subListener = new MessageCollector(); m_client.setCallback(subListener); m_client.connect(options); m_client.publish("/topic", "Test my payload".getBytes(), 0, false); - //Ugly, we need to get self notified after the publish + // Ugly, we need to get self notified after the publish assertEquals("Test my payload", new String(subListener.waitMessage(1).getPayload())); - //close + // close m_client.disconnect(); } @@ -192,7 +189,7 @@ public class ServerIntegrationPahoTest { m_server.startServer(IntegrationUtils.prepareTestProperties()); - //reconnect and publish + // reconnect and publish m_client.connect(options); m_client.publish("/topic", "Test my payload".getBytes(), 0, false); @@ -206,7 +203,7 @@ public class ServerIntegrationPahoTest { m_client.publish("/topic", "Test my payload".getBytes(), 1, true); m_client.disconnect(); - //reconnect and publish + // reconnect and publish m_client.connect(); m_client.subscribe("/topic", 0); @@ -221,7 +218,7 @@ public class ServerIntegrationPahoTest { m_client.connect(options); m_client.subscribe("/topic", 0); m_client.publish("/topic", "Test my payload".getBytes(), 0, false); - //m_client.disconnect(); + // m_client.disconnect(); assertEquals("/topic", m_messagesCollector.getTopic()); m_client.unsubscribe("/topic"); @@ -239,7 +236,7 @@ public class ServerIntegrationPahoTest { m_client.connect(options); m_client.subscribe("/topic", 0); m_client.publish("/topic", "Test my payload".getBytes(), 0, false); - //m_client.disconnect(); + // m_client.disconnect(); assertEquals("/topic", m_messagesCollector.getTopic()); m_client.unsubscribe("/topic"); @@ -260,7 +257,7 @@ public class ServerIntegrationPahoTest { m_client.publish("/topic", "Hello MQTT".getBytes(), 1, false); m_client.disconnect(); - //reconnect and publish + // reconnect and publish MqttMessage message = m_messagesCollector.waitMessage(1); assertEquals("Hello MQTT", message.toString()); assertEquals(1, message.getQos()); @@ -275,7 +272,7 @@ public class ServerIntegrationPahoTest { m_client.subscribe("/topic", 1); m_client.disconnect(); - //publish a QoS 1 message another client publish a message on the topic + // publish a QoS 1 message another client publish a message on the topic publishFromAnotherClient("/topic", "Hello MQTT".getBytes(), 1); m_client.connect(options); @@ -283,7 +280,6 @@ public class ServerIntegrationPahoTest { assertEquals("Hello MQTT", m_messagesCollector.waitMessage(1).toString()); } - @Test public void checkReceivePublishedMessage_after_a_reconnect_with_notCleanSession() throws Exception { LOG.info("*** checkReceivePublishedMessage_after_a_reconnect_with_notCleanSession ***"); @@ -296,10 +292,10 @@ public class ServerIntegrationPahoTest { m_client.connect(options); m_client.subscribe("/topic", 1); - //publish a QoS 1 message another client publish a message on the topic + // publish a QoS 1 message another client publish a message on the topic publishFromAnotherClient("/topic", "Hello MQTT".getBytes(), 1); - //Verify that after a reconnection the client receive the message + // Verify that after a reconnection the client receive the message MqttMessage message = m_messagesCollector.waitMessage(1); assertNotNull(message); assertEquals("Hello MQTT", message.toString()); @@ -321,7 +317,7 @@ public class ServerIntegrationPahoTest { m_client.subscribe("/topic", 2); m_client.disconnect(); - //publish a QoS 1 message another client publish a message on the topic + // publish a QoS 1 message another client publish a message on the topic publishFromAnotherClient("/topic", "Hello MQTT".getBytes(), 2); m_messagesCollector.reinit(); m_client.connect(options); @@ -340,7 +336,7 @@ public class ServerIntegrationPahoTest { m_client.subscribe("/topic", 2); m_client.disconnect(); - //publish a QoS 2 message another client publish a message on the topic + // publish a QoS 2 message another client publish a message on the topic publishFromAnotherClient("/topic", "Hello MQTT".getBytes(), 2); m_messagesCollector.reinit(); m_client.connect(options); @@ -370,10 +366,10 @@ public class ServerIntegrationPahoTest { assertEquals("Hello MQTT 1", message.toString()); m_client.disconnect(); - //publish other message + // publish other message publishFromAnotherClient("/topic", "Hello MQTT 2".getBytes(), 1); - //reconnect the second time + // reconnect the second time m_messagesCollector.reinit(); m_client.connect(options); assertNotNull(m_messagesCollector); @@ -383,11 +379,9 @@ public class ServerIntegrationPahoTest { } /** - * subscriber A connect and subscribe on "a/b" QoS 1 - * subscriber B connect and subscribe on "a/+" BUT with QoS 2 - * publisher connects and send a message "hello" on "a/b" - * subscriber A must receive a notification with QoS1 - * subscriber B must receive a notification with QoS2 + * subscriber A connect and subscribe on "a/b" QoS 1 subscriber B connect and subscribe on "a/+" + * BUT with QoS 2 publisher connects and send a message "hello" on "a/b" subscriber A must + * receive a notification with QoS1 subscriber B must receive a notification with QoS2 */ @Test public void checkSubscribersGetCorrectQosNotifications() throws Exception { @@ -410,7 +404,6 @@ public class ServerIntegrationPahoTest { subscriberB.connect(); subscriberB.subscribe("a/+", 2); - m_client.connect(); m_client.publish("a/b", "Hello world MQTT!!".getBytes(), 2, false); @@ -429,8 +422,9 @@ public class ServerIntegrationPahoTest { public void testSubcriptionDoesntStayActiveAfterARestart() throws Exception { LOG.info("*** testSubcriptionDoesntStayActiveAfterARestart ***"); String tmpDir = System.getProperty("java.io.tmpdir"); - //clientForSubscribe1 connect and subscribe to /topic QoS2 - MqttClientPersistence dsSubscriberA = new MqttDefaultFilePersistence(tmpDir + File.separator + "clientForSubscribe1"); + // clientForSubscribe1 connect and subscribe to /topic QoS2 + MqttClientPersistence dsSubscriberA = new MqttDefaultFilePersistence( + tmpDir + File.separator + "clientForSubscribe1"); MqttClient clientForSubscribe1 = new MqttClient("tcp://localhost:1883", "clientForSubscribe1", dsSubscriberA); MessageCollector cbSubscriber1 = new MessageCollector(); @@ -438,27 +432,29 @@ public class ServerIntegrationPahoTest { clientForSubscribe1.connect(); clientForSubscribe1.subscribe("topic", 0); - //server stop + // server stop m_server.stopServer(); System.out.println("\n\n SEVER REBOOTING \n\n"); - //server start + // server start startServer(); - //clientForSubscribe2 connect and subscribe to /topic QoS2 - MqttClientPersistence dsSubscriberB = new MqttDefaultFilePersistence(tmpDir + File.separator + "clientForSubscribe2"); + // clientForSubscribe2 connect and subscribe to /topic QoS2 + MqttClientPersistence dsSubscriberB = new MqttDefaultFilePersistence( + tmpDir + File.separator + "clientForSubscribe2"); MqttClient clientForSubscribe2 = new MqttClient("tcp://localhost:1883", "clientForSubscribe2", dsSubscriberB); MessageCollector cbSubscriber2 = new MessageCollector(); clientForSubscribe2.setCallback(cbSubscriber2); clientForSubscribe2.connect(); clientForSubscribe2.subscribe("topic", 0); - //clientForPublish publish on /topic with QoS2 a message - MqttClientPersistence dsSubscriberPUB = new MqttDefaultFilePersistence(tmpDir + File.separator + "clientForPublish"); + // clientForPublish publish on /topic with QoS2 a message + MqttClientPersistence dsSubscriberPUB = new MqttDefaultFilePersistence( + tmpDir + File.separator + "clientForPublish"); MqttClient clientForPublish = new MqttClient("tcp://localhost:1883", "clientForPublish", dsSubscriberPUB); clientForPublish.connect(); clientForPublish.publish("topic", "Hello".getBytes(), 2, true); - //verify clientForSubscribe1 doesn't receive a notification but clientForSubscribe2 yes + // verify clientForSubscribe1 doesn't receive a notification but clientForSubscribe2 yes LOG.info("Before waiting to receive 1 sec from " + clientForSubscribe1.getClientId()); assertFalse(clientForSubscribe1.isConnected()); assertTrue(clientForSubscribe2.isConnected()); @@ -490,7 +486,7 @@ public class ServerIntegrationPahoTest { MqttClient clientYB = createClient("publisher", "Y"); clientYB.publish("topic", "Hello 2".getBytes(), 2, true); - //Verify that the second subscriber client get notified and not the first. + // Verify that the second subscriber client get notified and not the first. assertTrue(cbSubscriber1.connectionLost()); assertEquals("Hello 2", new String(cbSubscriber2.waitMessage(1).getPayload())); } @@ -505,11 +501,11 @@ public class ServerIntegrationPahoTest { m_client.publish("/topic", "Hello".getBytes(), 0, true); m_client.disconnect(); - //second loop + // second loop m_client.connect(options); m_client.subscribe("/topic", 0); m_client.publish("/topic", "Hello".getBytes(), 0, true); - m_client.disconnect(); //this should give timeout + m_client.disconnect(); // this should give timeout assertFalse("after a disconnect the client should be disconnected", m_client.isConnected()); } @@ -517,8 +513,8 @@ public class ServerIntegrationPahoTest { @Test public void checkReplayofStoredPublishResumeAfter_a_disconnect_cleanSessionFalseQoS1() throws Exception { LOG.info("*** checkReplayofStoredPublishResumeAfter_a_disconnect_cleanSessionFalseQoS1 ***"); -// MessageCollector m_messagesCollector = new MessageCollector(); -// m_client.setCallback(m_messagesCollector); + // MessageCollector m_messagesCollector = new MessageCollector(); + // m_client.setCallback(m_messagesCollector); m_publisher.connect(); MqttConnectOptions options = new MqttConnectOptions(); @@ -526,10 +522,10 @@ public class ServerIntegrationPahoTest { m_client.connect(options); m_client.subscribe("/topic", 1); - //force the publisher to send + // force the publisher to send m_publisher.publish("/topic", "Hello world MQTT!!-1".getBytes(), 1, false); - //read the first message and drop the connection + // read the first message and drop the connection MqttMessage msg = m_messagesCollector.waitMessage(1); assertEquals("Hello world MQTT!!-1", new String(msg.getPayload())); m_client.disconnect(); @@ -537,7 +533,7 @@ public class ServerIntegrationPahoTest { m_publisher.publish("/topic", "Hello world MQTT!!-2".getBytes(), 1, false); m_publisher.publish("/topic", "Hello world MQTT!!-3".getBytes(), 1, false); - //reconnect and expect to receive the hello 2 message + // reconnect and expect to receive the hello 2 message m_client.connect(options); msg = m_messagesCollector.waitMessage(1); assertEquals("Hello world MQTT!!-2", new String(msg.getPayload())); @@ -560,10 +556,10 @@ public class ServerIntegrationPahoTest { m_client.subscribe("/topic", 1); m_client.disconnect(); - //force the publisher to send + // force the publisher to send m_publisher.publish("/topic", "Hello world MQTT!!-1".getBytes(), 1, false); - //reconnect and expect to receive the hello 2 message + // reconnect and expect to receive the hello 2 message m_client.connect(options); m_client.subscribe("/topic", 1); MqttMessage msg = messagesCollector.waitMessage(1); @@ -572,10 +568,9 @@ public class ServerIntegrationPahoTest { } /** - * subscriber connect and subscribe on "topic" - * subscriber disconnects - * publisher connects and send two message "hello1" "hello2" to "topic" - * subscriber connects again and receive "hello1" "hello2" + * subscriber connect and subscribe on "topic" subscriber disconnects publisher connects and + * send two message "hello1" "hello2" to "topic" subscriber connects again and receive "hello1" + * "hello2" */ @Test public void checkQoS2SubscriberDisconnectReceivePersistedPublishes() throws Exception { @@ -593,9 +588,9 @@ public class ServerIntegrationPahoTest { m_publisher.publish("topic", "Hello2".getBytes(), 2, true); m_publisher.disconnect(); - //subscriber reconnects + // subscriber reconnects m_client.connect(options); - //subscriber should receive the 2 messages missed + // subscriber should receive the 2 messages missed MqttMessage msg = messagesCollector.waitMessage(1); assertNotNull(msg); assertEquals("Hello1", new String(msg.getPayload())); @@ -605,9 +600,8 @@ public class ServerIntegrationPahoTest { } /** - * subscriber connect and subscribe on "a/b" QoS 1 and "a/+" QoS 2 - * publisher connects and send a message "hello" on "a/b" - * subscriber must receive only a single message not twice + * subscriber connect and subscribe on "a/b" QoS 1 and "a/+" QoS 2 publisher connects and send a + * message "hello" on "a/b" subscriber must receive only a single message not twice */ @Test public void checkSinglePublishOnOverlappingSubscriptions() throws Exception { @@ -622,27 +616,27 @@ public class ServerIntegrationPahoTest { m_client.subscribe("a/+", 2); m_client.subscribe("a/b", 1); - //force the publisher to send + // force the publisher to send m_publisher.publish("a/b", "Hello world MQTT!!".getBytes(), 1, false); - //reconnect and expect to receive the hello 2 message + // reconnect and expect to receive the hello 2 message MqttMessage msg = messagesCollector.waitMessage(1); assertEquals("Hello world MQTT!!", new String(msg.getPayload())); - //try to listen a second publish + // try to listen a second publish msg = messagesCollector.waitMessage(1); assertNull(msg); } - protected MqttClient createClient(String clientName, String storeSuffix) throws MqttException { return createClient(clientName, storeSuffix, null); } protected MqttClient createClient(String clientName, String storeSuffix, MessageCollector cb) throws MqttException { String tmpDir = System.getProperty("java.io.tmpdir"); - //clientX connect and subscribe to /topic QoS2 - MqttClientPersistence dsClient = new MqttDefaultFilePersistence(tmpDir + File.separator + storeSuffix + clientName); + // clientX connect and subscribe to /topic QoS2 + MqttClientPersistence dsClient = new MqttDefaultFilePersistence( + tmpDir + File.separator + storeSuffix + clientName); MqttClient client = new MqttClient("tcp://localhost:1883", clientName, dsClient); if (cb != null) { client.setCallback(cb); diff --git a/broker/src/test/java/io/moquette/server/ServerIntegrationQoSValidationTest.java b/broker/src/test/java/io/moquette/server/ServerIntegrationQoSValidationTest.java index 83be0c9f..9a6fcbb6 100644 --- a/broker/src/test/java/io/moquette/server/ServerIntegrationQoSValidationTest.java +++ b/broker/src/test/java/io/moquette/server/ServerIntegrationQoSValidationTest.java @@ -13,8 +13,8 @@ * * You may elect to redistribute this code under either of these licenses. */ -package io.moquette.server; +package io.moquette.server; import io.moquette.server.config.IConfig; import io.moquette.server.config.MemoryConfig; @@ -29,11 +29,9 @@ import org.junit.BeforeClass; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.io.File; import java.io.IOException; import java.util.Properties; - import static org.junit.Assert.assertEquals; /** @@ -41,13 +39,13 @@ import static org.junit.Assert.assertEquals; * @author andrea */ public class ServerIntegrationQoSValidationTest { - + private static final Logger LOG = LoggerFactory.getLogger(ServerIntegrationPahoTest.class); Server m_server; static MqttClientPersistence s_subDataStore; static MqttClientPersistence s_pubDataStore; - + IMqttClient m_subscriber; IMqttClient m_publisher; MessageCollector m_callback; @@ -75,7 +73,7 @@ public class ServerIntegrationQoSValidationTest { m_callback = new MessageCollector(); m_subscriber.setCallback(m_callback); m_subscriber.connect(); - + m_publisher = new MqttClient("tcp://localhost:1883", "Publisher", s_pubDataStore); m_publisher.connect(); } @@ -85,7 +83,7 @@ public class ServerIntegrationQoSValidationTest { if (m_publisher.isConnected()) { m_publisher.disconnect(); } - + if (m_subscriber.isConnected()) { m_subscriber.disconnect(); } @@ -93,104 +91,104 @@ public class ServerIntegrationQoSValidationTest { m_server.stopServer(); IntegrationUtils.cleanPersistenceFile(m_config); } - + @Test public void checkSubscriberQoS0ReceiveQoS0publishes() throws Exception { LOG.info("*** checkSubscriberQoS0ReceiveQoS0publishes ***"); m_subscriber.subscribe("/topic", 0); - + m_publisher.publish("/topic", "Hello world MQTT QoS0".getBytes(), 0, false); MqttMessage message = m_callback.waitMessage(1); assertEquals("Hello world MQTT QoS0", message.toString()); assertEquals(0, message.getQos()); } - + @Test public void checkSubscriberQoS0ReceiveQoS1publishes_downgrade() throws Exception { LOG.info("*** checkSubscriberQoS0ReceiveQoS1publishes_downgrade ***"); m_subscriber.subscribe("/topic", 0); - + m_publisher.publish("/topic", "Hello world MQTT QoS1".getBytes(), 1, false); MqttMessage message = m_callback.waitMessage(1); assertEquals("Hello world MQTT QoS1", message.toString()); assertEquals(0, message.getQos()); } - + @Test public void checkSubscriberQoS0ReceiveQoS2publishes_downgrade() throws Exception { LOG.info("*** checkSubscriberQoS0ReceiveQoS2publishes_downgrade ***"); m_subscriber.subscribe("/topic", 0); - + m_publisher.publish("/topic", "Hello world MQTT QoS2".getBytes(), 2, false); MqttMessage message = m_callback.waitMessage(1); assertEquals("Hello world MQTT QoS2", message.toString()); assertEquals(0, message.getQos()); } - + @Test public void checkSubscriberQoS1ReceiveQoS0publishes() throws Exception { LOG.info("*** checkSubscriberQoS1ReceiveQoS0publishes ***"); m_subscriber.subscribe("/topic", 1); - + m_publisher.publish("/topic", "Hello world MQTT QoS0".getBytes(), 0, false); MqttMessage message = m_callback.waitMessage(1); assertEquals("Hello world MQTT QoS0", message.toString()); assertEquals(0, message.getQos()); } - + @Test public void checkSubscriberQoS1ReceiveQoS1publishes() throws Exception { LOG.info("*** checkSubscriberQoS1ReceiveQoS1publishes ***"); m_subscriber.subscribe("/topic", 1); - + m_publisher.publish("/topic", "Hello world MQTT QoS1".getBytes(), 1, false); MqttMessage message = m_callback.waitMessage(1); assertEquals("Hello world MQTT QoS1", message.toString()); assertEquals(1, message.getQos()); } - + @Test public void checkSubscriberQoS1ReceiveQoS2publishes_downgrade() throws Exception { LOG.info("*** checkSubscriberQoS1ReceiveQoS2publishes_downgrade ***"); m_subscriber.subscribe("/topic", 1); - + m_publisher.publish("/topic", "Hello world MQTT QoS2".getBytes(), 2, false); MqttMessage message = m_callback.waitMessage(1); assertEquals("Hello world MQTT QoS2", message.toString()); assertEquals(1, message.getQos()); } - + @Test public void checkSubscriberQoS2ReceiveQoS0publishes() throws Exception { LOG.info("*** checkSubscriberQoS2ReceiveQoS0publishes ***"); m_subscriber.subscribe("/topic", 2); - + m_publisher.publish("/topic", "Hello world MQTT QoS2".getBytes(), 0, false); MqttMessage message = m_callback.waitMessage(1); assertEquals("Hello world MQTT QoS2", message.toString()); assertEquals(0, message.getQos()); } - + @Test public void checkSubscriberQoS2ReceiveQoS1publishes() throws Exception { LOG.info("*** checkSubscriberQoS2ReceiveQoS1publishes ***"); m_subscriber.subscribe("/topic", 2); - + m_publisher.publish("/topic", "Hello world MQTT QoS2".getBytes(), 1, false); MqttMessage message = m_callback.waitMessage(1); assertEquals("Hello world MQTT QoS2", message.toString()); assertEquals(1, message.getQos()); } - + @Test public void checkSubscriberQoS2ReceiveQoS2publishes() throws Exception { LOG.info("*** checkSubscriberQoS2ReceiveQoS2publishes ***"); m_subscriber.subscribe("/topic", 2); - + m_publisher.publish("/topic", "Hello world MQTT QoS2".getBytes(), 2, false); MqttMessage message = m_callback.waitMessage(1); assertEquals("Hello world MQTT QoS2", message.toString()); assertEquals(2, message.getQos()); } - + } diff --git a/broker/src/test/java/io/moquette/server/ServerIntegrationSSLClientAuthTest.java b/broker/src/test/java/io/moquette/server/ServerIntegrationSSLClientAuthTest.java index 99f01077..1bb19594 100644 --- a/broker/src/test/java/io/moquette/server/ServerIntegrationSSLClientAuthTest.java +++ b/broker/src/test/java/io/moquette/server/ServerIntegrationSSLClientAuthTest.java @@ -13,10 +13,10 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server; import static org.junit.Assert.assertFalse; - import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -27,13 +27,11 @@ import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.util.Properties; - import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; - import io.moquette.BrokerConstants; import org.eclipse.paho.client.mqttv3.IMqttClient; import org.eclipse.paho.client.mqttv3.MqttClient; @@ -50,46 +48,49 @@ import org.slf4j.LoggerFactory; /** * Check that Moquette could also handle SSL with client authentication. - * + * *

* Create certificates needed for client authentication + * *

  * # generate server certificate chain (valid for 10000 days)
- * keytool -genkeypair -alias signedtestserver -dname cn=moquette.eclipse.org -keyalg RSA -keysize 2048 -keystore signedserverkeystore.jks -keypass passw0rdsrv -storepass passw0rdsrv -validity 10000 
+ * keytool -genkeypair -alias signedtestserver -dname cn=moquette.eclipse.org -keyalg RSA -keysize 2048 -keystore signedserverkeystore.jks -keypass passw0rdsrv -storepass passw0rdsrv -validity 10000
  * keytool -genkeypair -alias signedtestserver_sub -dname cn=moquette.eclipse.org -keyalg RSA -keysize 2048 -keystore signedserverkeystore.jks -keypass passw0rdsrv -storepass passw0rdsrv
- * 
- * # sign server subcertificate with server certificate (valid for 10000 days) 
+ *
+ * # sign server subcertificate with server certificate (valid for 10000 days)
  * keytool -certreq -alias signedtestserver_sub -keystore signedserverkeystore.jks -keypass passw0rdsrv -storepass passw0rdsrv | \
- * 	keytool -gencert -alias signedtestserver -keystore signedserverkeystore.jks -keypass passw0rdsrv -storepass passw0rdsrv -validity 10000 | \
- * 	keytool -importcert -alias signedtestserver_sub -keystore signedserverkeystore.jks -keypass passw0rdsrv -storepass passw0rdsrv
- * 
+ * keytool -gencert -alias signedtestserver -keystore signedserverkeystore.jks -keypass passw0rdsrv -storepass passw0rdsrv -validity 10000 | \
+ * keytool -importcert -alias signedtestserver_sub -keystore signedserverkeystore.jks -keypass passw0rdsrv -storepass passw0rdsrv
+ *
  * # generate client keypair
  * keytool -genkeypair -alias signedtestclient -dname cn=moquette.eclipse.org -keyalg RSA -keysize 2048 -keystore signedclientkeystore.jks -keypass passw0rd -storepass passw0rd
- * 
- * # create signed client certificate with server subcertificate and import to client keystore (valid for 10000 days) 
+ *
+ * # create signed client certificate with server subcertificate and import to client keystore (valid for 10000 days)
  * keytool -certreq -alias signedtestclient -keystore signedclientkeystore.jks -keypass passw0rd -storepass passw0rd | \
- *  keytool -gencert -alias signedtestserver_sub -keystore signedserverkeystore.jks -keypass passw0rdsrv -storepass passw0rdsrv -validity 10000 | \
- *  keytool -importcert -alias signedtestclient -keystore signedclientkeystore.jks -keypass passw0rd -storepass passw0rd -noprompt
- * 
+ * keytool -gencert -alias signedtestserver_sub -keystore signedserverkeystore.jks -keypass passw0rdsrv -storepass passw0rdsrv -validity 10000 | \
+ * keytool -importcert -alias signedtestclient -keystore signedclientkeystore.jks -keypass passw0rd -storepass passw0rd -noprompt
+ *
  * # import server certificates into signed truststore
  * keytool -exportcert -alias signedtestserver -keystore signedserverkeystore.jks -keypass passw0rdsrv -storepass passw0rdsrv | \
- *  keytool -importcert -trustcacerts -noprompt -alias signedtestserver -keystore signedclientkeystore.jks -keypass passw0rd -storepass passw0rd
+ * keytool -importcert -trustcacerts -noprompt -alias signedtestserver -keystore signedclientkeystore.jks -keypass passw0rd -storepass passw0rd
  * keytool -exportcert -alias signedtestserver_sub -keystore signedserverkeystore.jks -keypass passw0rdsrv -storepass passw0rdsrv | \
- *  keytool -importcert -trustcacerts -noprompt -alias signedtestserver_sub -keystore signedclientkeystore.jks -keypass passw0rd -storepass passw0rd
- * 
+ * keytool -importcert -trustcacerts -noprompt -alias signedtestserver_sub -keystore signedclientkeystore.jks -keypass passw0rd -storepass passw0rd
+ *
  * # create unsigned client certificate (valid for 10000 days)
  * keytool -genkeypair -alias unsignedtestclient -dname cn=moquette.eclipse.org -validity 10000 -keyalg RSA -keysize 2048 -keystore unsignedclientkeystore.jks -keypass passw0rd -storepass passw0rd
- * 
+ *
  * # import server certificates into unsigned truststore
  * keytool -exportcert -alias signedtestserver -keystore signedserverkeystore.jks -keypass passw0rdsrv -storepass passw0rdsrv | \
- *  keytool -importcert -trustcacerts -noprompt -alias signedtestserver -keystore unsignedclientkeystore.jks -keypass passw0rd -storepass passw0rd
+ * keytool -importcert -trustcacerts -noprompt -alias signedtestserver -keystore unsignedclientkeystore.jks -keypass passw0rd -storepass passw0rd
  * keytool -exportcert -alias signedtestserver_sub -keystore signedserverkeystore.jks -keypass passw0rdsrv -storepass passw0rdsrv | \
- *  keytool -importcert -trustcacerts -noprompt -alias signedtestserver_sub -keystore unsignedclientkeystore.jks -keypass passw0rd -storepass passw0rd
+ * keytool -importcert -trustcacerts -noprompt -alias signedtestserver_sub -keystore unsignedclientkeystore.jks -keypass passw0rd -storepass passw0rd
  * 
*

+ * * @author andrea / konradm */ public class ServerIntegrationSSLClientAuthTest { + private static final Logger LOG = LoggerFactory.getLogger(ServerIntegrationSSLClientAuthTest.class); Server m_server; @@ -128,8 +129,8 @@ public class ServerIntegrationSSLClientAuthTest { startServer(); m_client = new MqttClient("ssl://localhost:8883", "TestClient", s_dataStore); -// m_client = new MqttClient("ssl://test.mosquitto.org:8883", "TestClient", s_dataStore); - + // m_client = new MqttClient("ssl://test.mosquitto.org:8883", "TestClient", s_dataStore); + m_callback = new MessageCollector(); m_client.setCallback(m_callback); } @@ -150,12 +151,12 @@ public class ServerIntegrationSSLClientAuthTest { } assertFalse(dbFile.exists()); } - + @Test public void checkClientAuthentication() throws Exception { LOG.info("*** checkClientAuthentication ***"); SSLSocketFactory ssf = configureSSLSocketFactory("signedclientkeystore.jks"); - + MqttConnectOptions options = new MqttConnectOptions(); options.setSocketFactory(ssf); m_client.connect(options); @@ -163,24 +164,24 @@ public class ServerIntegrationSSLClientAuthTest { m_client.disconnect(); } - @Test (expected = MqttException.class) + @Test(expected = MqttException.class) public void checkClientAuthenticationFail() throws Exception { LOG.info("*** checkClientAuthenticationFail ***"); SSLSocketFactory ssf = configureSSLSocketFactory("unsignedclientkeystore.jks"); - + MqttConnectOptions options = new MqttConnectOptions(); options.setSocketFactory(ssf); // actual a "Broken pipe" is thrown, this is not very specific. try { - m_client.connect(options); - }catch(MqttException e) - { - e.printStackTrace(); - throw e; + m_client.connect(options); + } catch (MqttException e) { + e.printStackTrace(); + throw e; } } - private SSLSocketFactory configureSSLSocketFactory(String keystore) throws KeyManagementException, NoSuchAlgorithmException, UnrecoverableKeyException, IOException, CertificateException, KeyStoreException { + private SSLSocketFactory configureSSLSocketFactory(String keystore) throws KeyManagementException, + NoSuchAlgorithmException, UnrecoverableKeyException, IOException, CertificateException, KeyStoreException { KeyStore ks = KeyStore.getInstance("JKS"); InputStream jksInputStream = getClass().getClassLoader().getResourceAsStream(keystore); ks.load(jksInputStream, "passw0rd".toCharArray()); @@ -191,9 +192,9 @@ public class ServerIntegrationSSLClientAuthTest { TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(ks); - SSLContext sc = SSLContext.getInstance("TLS"); - TrustManager[] trustManagers = tmf.getTrustManagers(); - sc.init(kmf.getKeyManagers(), trustManagers, null); + SSLContext sc = SSLContext.getInstance("TLS"); + TrustManager[] trustManagers = tmf.getTrustManagers(); + sc.init(kmf.getKeyManagers(), trustManagers, null); SSLSocketFactory ssf = sc.getSocketFactory(); return ssf; diff --git a/broker/src/test/java/io/moquette/server/ServerIntegrationSSLTest.java b/broker/src/test/java/io/moquette/server/ServerIntegrationSSLTest.java index 9dd9b2cc..3abee018 100644 --- a/broker/src/test/java/io/moquette/server/ServerIntegrationSSLTest.java +++ b/broker/src/test/java/io/moquette/server/ServerIntegrationSSLTest.java @@ -13,10 +13,10 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server; import static org.junit.Assert.assertFalse; - import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -27,13 +27,11 @@ import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.util.Properties; - import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; - import io.moquette.BrokerConstants; import org.eclipse.paho.client.mqttv3.IMqttClient; import org.eclipse.paho.client.mqttv3.MqttClient; @@ -51,10 +49,11 @@ import org.slf4j.LoggerFactory; /** * Check that Moquette could also handle SSL. - * + * * @author andrea */ public class ServerIntegrationSSLTest { + private static final Logger LOG = LoggerFactory.getLogger(ServerIntegrationSSLTest.class); Server m_server; @@ -92,8 +91,8 @@ public class ServerIntegrationSSLTest { startServer(); m_client = new MqttClient("ssl://localhost:8883", "TestClient", s_dataStore); -// m_client = new MqttClient("ssl://test.mosquitto.org:8883", "TestClient", s_dataStore); - + // m_client = new MqttClient("ssl://test.mosquitto.org:8883", "TestClient", s_dataStore); + m_callback = new MessageCollector(); m_client.setCallback(m_callback); } @@ -114,12 +113,12 @@ public class ServerIntegrationSSLTest { } assertFalse(dbFile.exists()); } - + @Test public void checkSupportSSL() throws Exception { LOG.info("*** checkSupportSSL ***"); SSLSocketFactory ssf = configureSSLSocketFactory(); - + MqttConnectOptions options = new MqttConnectOptions(); options.setSocketFactory(ssf); m_client.connect(options); @@ -131,38 +130,38 @@ public class ServerIntegrationSSLTest { public void checkSupportSSLForMultipleClient() throws Exception { LOG.info("*** checkSupportSSLForMultipleClient ***"); SSLSocketFactory ssf = configureSSLSocketFactory(); - + MqttConnectOptions options = new MqttConnectOptions(); options.setSocketFactory(ssf); m_client.connect(options); m_client.subscribe("/topic", 0); - + MqttClient secondClient = new MqttClient("ssl://localhost:8883", "secondTestClient", new MemoryPersistence()); MqttConnectOptions secondClientOptions = new MqttConnectOptions(); secondClientOptions.setSocketFactory(ssf); secondClient.connect(secondClientOptions); secondClient.publish("/topic", new MqttMessage("message".getBytes())); secondClient.disconnect(); - + m_client.disconnect(); } + /** * keystore generated into test/resources with command: - * - * keytool -keystore clientkeystore.jks -alias testclient -genkey -keyalg RSA - * -> mandatory to put the name surname - * -> password is passw0rd - * -> type yes at the end - * - * to generate the crt file from the keystore - * -- keytool -certreq -alias testclient -keystore clientkeystore.jks -file testclient.csr - * + * + * keytool -keystore clientkeystore.jks -alias testclient -genkey -keyalg RSA -> mandatory to + * put the name surname -> password is passw0rd -> type yes at the end + * + * to generate the crt file from the keystore -- keytool -certreq -alias testclient -keystore + * clientkeystore.jks -file testclient.csr + * * keytool -export -alias testclient -keystore clientkeystore.jks -file testclient.crt - * - * to import an existing certificate: - * keytool -keystore clientkeystore.jks -import -alias testclient -file testclient.crt -trustcacerts + * + * to import an existing certificate: keytool -keystore clientkeystore.jks -import -alias + * testclient -file testclient.crt -trustcacerts */ - private SSLSocketFactory configureSSLSocketFactory() throws KeyManagementException, NoSuchAlgorithmException, UnrecoverableKeyException, IOException, CertificateException, KeyStoreException { + private SSLSocketFactory configureSSLSocketFactory() throws KeyManagementException, NoSuchAlgorithmException, + UnrecoverableKeyException, IOException, CertificateException, KeyStoreException { KeyStore ks = KeyStore.getInstance("JKS"); InputStream jksInputStream = getClass().getClassLoader().getResourceAsStream("clientkeystore.jks"); ks.load(jksInputStream, "passw0rd".toCharArray()); @@ -173,9 +172,9 @@ public class ServerIntegrationSSLTest { TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(ks); - SSLContext sc = SSLContext.getInstance("TLS"); - TrustManager[] trustManagers = tmf.getTrustManagers(); - sc.init(kmf.getKeyManagers(), trustManagers, null); + SSLContext sc = SSLContext.getInstance("TLS"); + TrustManager[] trustManagers = tmf.getTrustManagers(); + sc.init(kmf.getKeyManagers(), trustManagers, null); SSLSocketFactory ssf = sc.getSocketFactory(); return ssf; diff --git a/broker/src/test/java/io/moquette/server/ServerIntegrationWebSocketTest.java b/broker/src/test/java/io/moquette/server/ServerIntegrationWebSocketTest.java index 05a364ef..b4ed8ac9 100644 --- a/broker/src/test/java/io/moquette/server/ServerIntegrationWebSocketTest.java +++ b/broker/src/test/java/io/moquette/server/ServerIntegrationWebSocketTest.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server; import io.moquette.BrokerConstants; @@ -25,21 +26,19 @@ import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.io.IOException; import java.net.URI; import java.util.Properties; import java.util.concurrent.TimeUnit; - import static org.junit.Assert.assertTrue; - /** * Integration test to check the function of Moquette with a WebSocket channel. - * + * * @author andrea */ public class ServerIntegrationWebSocketTest { + private static final Logger LOG = LoggerFactory.getLogger(ServerIntegrationWebSocketTest.class); Server m_server; @@ -49,7 +48,8 @@ public class ServerIntegrationWebSocketTest { protected void startServer() throws IOException { m_server = new Server(); final Properties configProps = IntegrationUtils.prepareTestProperties(); - configProps.put(BrokerConstants.WEB_SOCKET_PORT_PROPERTY_NAME, Integer.toString(BrokerConstants.WEBSOCKET_PORT)); + configProps + .put(BrokerConstants.WEB_SOCKET_PORT_PROPERTY_NAME, Integer.toString(BrokerConstants.WEBSOCKET_PORT)); m_config = new MemoryConfig(configProps); m_server.startServer(m_config); } @@ -63,16 +63,16 @@ public class ServerIntegrationWebSocketTest { @After public void tearDown() throws Exception { client.stop(); - + m_server.stopServer(); IntegrationUtils.cleanPersistenceFile(m_config); } - + @Test public void checkPlainConnect() throws Exception { LOG.info("*** checkPlainConnect ***"); String destUri = "ws://localhost:" + BrokerConstants.WEBSOCKET_PORT + "/mqtt"; - + MQTTWebSocket socket = new MQTTWebSocket(); client.start(); URI echoUri = new URI(destUri); diff --git a/broker/src/test/java/io/moquette/server/ServerLowlevelMessagesIntegrationTests.java b/broker/src/test/java/io/moquette/server/ServerLowlevelMessagesIntegrationTests.java index 914ba1e7..3b3890a8 100644 --- a/broker/src/test/java/io/moquette/server/ServerLowlevelMessagesIntegrationTests.java +++ b/broker/src/test/java/io/moquette/server/ServerLowlevelMessagesIntegrationTests.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server; import io.moquette.server.config.IConfig; @@ -26,7 +27,6 @@ import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.io.IOException; import java.util.Properties; import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.*; @@ -37,6 +37,7 @@ import static org.junit.Assert.*; * @author andrea */ public class ServerLowlevelMessagesIntegrationTests { + private static final Logger LOG = LoggerFactory.getLogger(ServerLowlevelMessagesIntegrationTests.class); static MqttClientPersistence s_dataStore; Server m_server; @@ -66,7 +67,7 @@ public class ServerLowlevelMessagesIntegrationTests { public void tearDown() throws Exception { m_client.close(); LOG.debug("After raw client close"); - Thread.sleep(300); //to let the close event pass before server stop event + Thread.sleep(300); // to let the close event pass before server stop event m_server.stopServer(); LOG.debug("After asked server to stop"); IntegrationUtils.cleanPersistenceFile(m_config); @@ -74,62 +75,67 @@ public class ServerLowlevelMessagesIntegrationTests { @Test public void elapseKeepAliveTime() throws InterruptedException { - int keepAlive = 2; //secs + int keepAlive = 2; // secs MqttConnectMessage connectMessage = createConnectMessage("FAKECLNT", keepAlive); - /*ConnectMessage connectMessage = new ConnectMessage(); - connectMessage.setProtocolVersion((byte) 3); - connectMessage.setClientID("FAKECLNT"); - connectMessage.setKeepAlive(keepAlive);*/ + /* + * ConnectMessage connectMessage = new ConnectMessage(); + * connectMessage.setProtocolVersion((byte) 3); connectMessage.setClientID("FAKECLNT"); + * connectMessage.setKeepAlive(keepAlive); + */ m_client.sendMessage(connectMessage); - - //wait 2 times the keepAlive + + // wait 2 times the keepAlive Thread.sleep(keepAlive * 2 * 1000); - + assertTrue(m_client.isConnectionLost()); } private static MqttConnectMessage createConnectMessage(String clientID, int keepAlive) { - MqttFixedHeader mqttFixedHeader = new MqttFixedHeader(MqttMessageType.CONNECT, false, MqttQoS.AT_MOST_ONCE, false, 0); - MqttConnectVariableHeader mqttConnectVariableHeader = - new MqttConnectVariableHeader( - MqttVersion.MQTT_3_1.protocolName(), - MqttVersion.MQTT_3_1.protocolLevel(), - false, - false, - false, - 1, - false, - true, - keepAlive); + MqttFixedHeader mqttFixedHeader = new MqttFixedHeader( + MqttMessageType.CONNECT, + false, + MqttQoS.AT_MOST_ONCE, + false, + 0); + MqttConnectVariableHeader mqttConnectVariableHeader = new MqttConnectVariableHeader( + MqttVersion.MQTT_3_1.protocolName(), + MqttVersion.MQTT_3_1.protocolLevel(), + false, + false, + false, + 1, + false, + true, + keepAlive); MqttConnectPayload mqttConnectPayload = new MqttConnectPayload(clientID, null, null, null, null); return new MqttConnectMessage(mqttFixedHeader, mqttConnectVariableHeader, mqttConnectPayload); } - + @Test public void testWillMessageIsWiredOnClientKeepAliveExpiry() throws Exception { LOG.info("*** testWillMessageIsWiredOnClientKeepAliveExpiry ***"); String willTestamentTopic = "/will/test"; String willTestamentMsg = "Bye bye"; - + m_willSubscriber.connect(); m_willSubscriber.subscribe(willTestamentTopic, 0); - + m_client.clientId("FAKECLNT").connect(willTestamentTopic, willTestamentMsg); long connectTime = System.currentTimeMillis(); - //but after the 2 KEEP ALIVE timeout expires it gets fired, - //NB it's 1,5 * KEEP_ALIVE so 3 secs and some millis to propagate the message + // but after the 2 KEEP ALIVE timeout expires it gets fired, + // NB it's 1,5 * KEEP_ALIVE so 3 secs and some millis to propagate the message org.eclipse.paho.client.mqttv3.MqttMessage msg = m_messageCollector.waitMessage(5); assertNotNull("the will message should be fired after keep alive!", msg); - //the will message hasn't to be received before the elapsing of Keep Alive timeout - assertTrue(System.currentTimeMillis() - connectTime > 3000); - + // the will message hasn't to be received before the elapsing of Keep Alive timeout + assertTrue(System.currentTimeMillis() - connectTime > 3000); + assertEquals(willTestamentMsg, new String(msg.getPayload())); m_willSubscriber.disconnect(); } - + @Test public void testRejectConnectWithEmptyClientID() throws InterruptedException { LOG.info("*** testRejectConnectWithEmptyClientID ***"); @@ -151,10 +157,10 @@ public class ServerLowlevelMessagesIntegrationTests { m_willSubscriber.subscribe(willTestamentTopic, 0); m_client.clientId("FAKECLNT").connect(willTestamentTopic, willTestamentMsg); - //kill will publisher + // kill will publisher m_client.close(); - //Verify will testament is published + // Verify will testament is published org.eclipse.paho.client.mqttv3.MqttMessage receivedTestament = m_messageCollector.waitMessage(1); assertEquals(willTestamentMsg, new String(receivedTestament.getPayload())); m_willSubscriber.disconnect(); diff --git a/broker/src/test/java/io/moquette/server/ServerRestartIntegrationTest.java b/broker/src/test/java/io/moquette/server/ServerRestartIntegrationTest.java index c8304eea..2c640459 100644 --- a/broker/src/test/java/io/moquette/server/ServerRestartIntegrationTest.java +++ b/broker/src/test/java/io/moquette/server/ServerRestartIntegrationTest.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server; import io.moquette.server.config.IConfig; @@ -23,7 +24,6 @@ import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; - import java.io.File; import java.io.IOException; import java.util.Properties; @@ -87,47 +87,45 @@ public class ServerRestartIntegrationTest { m_server.stopServer(); IntegrationUtils.cleanPersistenceFile(m_config); } - - + @Test public void checkRestartCleanSubscriptionTree() throws Exception { - //subscribe to /topic + // subscribe to /topic m_subscriber.connect(CLEAN_SESSION_OPT); m_subscriber.subscribe("/topic", 1); m_subscriber.disconnect(); - - //shutdown the server + + // shutdown the server m_server.stopServer(); IntegrationUtils.cleanPersistenceFile(m_config); - //restart the server + // restart the server m_server.startServer(IntegrationUtils.prepareTestProperties()); - - //reconnect the Subscriber subscribing to the same /topic but different QoS + + // reconnect the Subscriber subscribing to the same /topic but different QoS m_subscriber.connect(CLEAN_SESSION_OPT); m_subscriber.subscribe("/topic", 2); - - //should be just one registration so a publisher receive one notification + + // should be just one registration so a publisher receive one notification m_publisher.connect(CLEAN_SESSION_OPT); m_publisher.publish("/topic", "Hello world MQTT!!".getBytes(), 1, false); - - //read the messages + + // read the messages MqttMessage msg = m_messageCollector.waitMessage(1); assertEquals("Hello world MQTT!!", new String(msg.getPayload())); - //no more messages on the same topic will be received + // no more messages on the same topic will be received assertNull(m_messageCollector.waitMessage(1)); } - @Test public void checkDontPublishInactiveClientsAfterServerRestart() throws Exception { IMqttClient conn = subscribeAndPublish("/topic"); conn.disconnect(); - //shutdown the server + // shutdown the server m_server.stopServer(); - //restart the server + // restart the server m_server.startServer(IntegrationUtils.prepareTestProperties()); m_publisher.connect(); @@ -136,37 +134,37 @@ public class ServerRestartIntegrationTest { @Test public void testClientDoesntRemainSubscribedAfterASubscriptionAndServerRestart() throws Exception { - //subscribe to /topic + // subscribe to /topic m_subscriber.connect(); - //subscribe /topic + // subscribe /topic m_subscriber.subscribe("/topic", 0); - //unsubscribe from /topic + // unsubscribe from /topic m_subscriber.unsubscribe("/topic"); m_subscriber.disconnect(); - //shutdown the server + // shutdown the server m_server.stopServer(); - //restart the server + // restart the server m_server.startServer(IntegrationUtils.prepareTestProperties()); - //subscriber reconnects + // subscriber reconnects m_subscriber = new MqttClient("tcp://localhost:1883", "Subscriber", s_dataStore); m_subscriber.setCallback(m_messageCollector); m_subscriber.connect(); - //publisher publishes on /topic + // publisher publishes on /topic m_publisher = new MqttClient("tcp://localhost:1883", "Publisher", s_pubDataStore); m_publisher.connect(); m_publisher.publish("/topic", "Hello world MQTT!!".getBytes(), 1, false); - //Expected - //the subscriber doesn't get notified (it's fully unsubscribed) + // Expected + // the subscriber doesn't get notified (it's fully unsubscribed) assertNull(m_messageCollector.waitMessage(1)); } /** * Connect subscribe to topic and publish on the same topic - * */ + */ private IMqttClient subscribeAndPublish(String topic) throws Exception { IMqttClient client = new MqttClient("tcp://localhost:1883", "SubPub"); MessageCollector collector = new MessageCollector(); @@ -178,4 +176,4 @@ public class ServerRestartIntegrationTest { assertEquals("Hello world MQTT!!", new String(msg.getPayload())); return client; } -} \ No newline at end of file +} diff --git a/broker/src/test/java/io/moquette/server/config/ClasspathResourceLoaderTest.java b/broker/src/test/java/io/moquette/server/config/ClasspathResourceLoaderTest.java index 1c8985bb..860d7c16 100644 --- a/broker/src/test/java/io/moquette/server/config/ClasspathResourceLoaderTest.java +++ b/broker/src/test/java/io/moquette/server/config/ClasspathResourceLoaderTest.java @@ -1,20 +1,19 @@ + package io.moquette.server.config; import static org.junit.Assert.*; - import org.junit.Test; - import io.moquette.BrokerConstants; public class ClasspathResourceLoaderTest { - @Test - public void testSetProperties() { - IResourceLoader classpathLoader = new ClasspathResourceLoader(); - final IConfig classPathConfig = new ResourceLoaderConfig(classpathLoader); - assertEquals(""+BrokerConstants.PORT,classPathConfig.getProperty(BrokerConstants.PORT_PROPERTY_NAME)); + @Test + public void testSetProperties() { + IResourceLoader classpathLoader = new ClasspathResourceLoader(); + final IConfig classPathConfig = new ResourceLoaderConfig(classpathLoader); + assertEquals("" + BrokerConstants.PORT, classPathConfig.getProperty(BrokerConstants.PORT_PROPERTY_NAME)); classPathConfig.setProperty(BrokerConstants.PORT_PROPERTY_NAME, "9999"); - assertEquals("9999",classPathConfig.getProperty(BrokerConstants.PORT_PROPERTY_NAME)); - } + assertEquals("9999", classPathConfig.getProperty(BrokerConstants.PORT_PROPERTY_NAME)); + } } diff --git a/broker/src/test/java/io/moquette/server/config/ConfigurationParserTest.java b/broker/src/test/java/io/moquette/server/config/ConfigurationParserTest.java index df786593..515dea40 100644 --- a/broker/src/test/java/io/moquette/server/config/ConfigurationParserTest.java +++ b/broker/src/test/java/io/moquette/server/config/ConfigurationParserTest.java @@ -13,17 +13,16 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.server.config; import io.moquette.BrokerConstants; import org.junit.Before; import org.junit.Test; - import java.io.Reader; import java.io.StringReader; import java.text.ParseException; import java.util.Properties; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -35,72 +34,69 @@ import static org.junit.Assert.assertTrue; public class ConfigurationParserTest { ConfigurationParser m_parser; - + @Before public void setUp() { m_parser = new ConfigurationParser(); } - + @Test public void checkDefaultOptions() { Properties props = m_parser.getProperties(); - - //verifyDefaults(props); + + // verifyDefaults(props); assertTrue(props.isEmpty()); } - + @Test public void parseEmpty() throws ParseException { Reader conf = new StringReader(" "); m_parser.parse(conf); - - //Verify -// verifyDefaults(m_parser.getProperties()); + + // Verify + // verifyDefaults(m_parser.getProperties()); assertTrue(m_parser.getProperties().isEmpty()); } - + @Test public void parseValidComment() throws ParseException { Reader conf = new StringReader("#simple comment"); m_parser.parse(conf); - - //Verify -// verifyDefaults(m_parser.getProperties()); + + // Verify + // verifyDefaults(m_parser.getProperties()); assertTrue(m_parser.getProperties().isEmpty()); } - + @Test(expected = ParseException.class) public void parseInvalidComment() throws ParseException { Reader conf = new StringReader(" #simple comment"); m_parser.parse(conf); - } - + } + @Test public void parseSingleVariable() throws ParseException { Reader conf = new StringReader("port 1234"); m_parser.parse(conf); - - //Verify + + // Verify assertEquals("1234", m_parser.getProperties().getProperty("port")); } - + @Test public void parseCompleteFile() throws ParseException { - String content = "# This is initial m_config format \r\n" - + " \r\n" - + "port 1234 \r\n" - + "host localhost \r\n" - + "fake multi word string property\r\n"; + String content = "# This is initial m_config format \r\n" + " \r\n" + "port 1234 \r\n" + + "host localhost \r\n" + "fake multi word string property\r\n"; Reader conf = new StringReader(content); m_parser.parse(conf); - - //Verify + + // Verify Properties props = m_parser.getProperties(); assertEquals("1234", props.getProperty("port")); assertEquals("localhost", props.getProperty("host")); assertEquals("multi word string property", props.getProperty("fake")); } - + /** * Helper method to verify default options. */ @@ -109,4 +105,4 @@ public class ConfigurationParserTest { assertEquals(BrokerConstants.HOST, props.getProperty(BrokerConstants.HOST_PROPERTY_NAME)); assertNull(props.getProperty(BrokerConstants.WEB_SOCKET_PORT_PROPERTY_NAME)); } -} \ No newline at end of file +} diff --git a/broker/src/test/java/io/moquette/spec/v3_1_1/connection/ConnectionIT.java b/broker/src/test/java/io/moquette/spec/v3_1_1/connection/ConnectionIT.java index 301b06ec..a81b32d0 100644 --- a/broker/src/test/java/io/moquette/spec/v3_1_1/connection/ConnectionIT.java +++ b/broker/src/test/java/io/moquette/spec/v3_1_1/connection/ConnectionIT.java @@ -13,14 +13,13 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spec.v3_1_1.connection; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; - import java.io.File; import java.io.IOException; - import io.moquette.BrokerConstants; import io.moquette.server.Server; import io.moquette.testclient.RawClient; @@ -32,12 +31,12 @@ import org.junit.Test; /** * * @author pkhanal - * + * */ public class ConnectionIT { - - Server m_server; - + + Server m_server; + protected void startServer() throws IOException { m_server = new Server(); m_server.startServer(); @@ -54,7 +53,9 @@ public class ConnectionIT { File dbFile = new File(BrokerConstants.DEFAULT_PERSISTENT_PATH); if (dbFile.exists()) { - assertTrue("Error deleting the moquette db file " + BrokerConstants.DEFAULT_PERSISTENT_PATH, dbFile.delete()); + assertTrue( + "Error deleting the moquette db file " + BrokerConstants.DEFAULT_PERSISTENT_PATH, + dbFile.delete()); } assertFalse(dbFile.exists()); } @@ -62,100 +63,103 @@ public class ConnectionIT { @Test(timeout = 3000) public void testConnectThenClose() throws Exception { RawClient.connect("127.0.0.1", 1883).isConnected() - //CONNECT - .write(0x10) //MQTT Control Packet type(1) - .write(0x13) // Remaining Length - .write(0x00, 0x04) // Protocol Name Length - .write("MQTT") // Protocol Name - .write(0x04) // The value of the Protocol Level field for the version 3.1.1 of the protocol is 4 (0x04) + // CONNECT + .write(0x10) // MQTT Control Packet type(1) + .write(0x13) // Remaining Length + .write(0x00, 0x04) // Protocol Name Length + .write("MQTT") // Protocol Name + .write(0x04) // The value of the Protocol Level field for the version 3.1.1 of the + // protocol is 4 (0x04) - //Connect Flags - //User Name Flag(0) - //Password Flag(0) - //Will Retain(0) - //Will QoS(00) - //Will Flag(0) - //Clean Session(1) - .write(0x02) // Reserved(0) - .write(0x00, 0x00) // Keep Alive + // Connect Flags + // User Name Flag(0) + // Password Flag(0) + // Will Retain(0) + // Will QoS(00) + // Will Flag(0) + // Clean Session(1) + .write(0x02) // Reserved(0) + .write(0x00, 0x00) // Keep Alive - // Payload - .write(0x00, 0x07) // Client Identifier Length - .write("client1") // Client Identifier - .flush() + // Payload + .write(0x00, 0x07) // Client Identifier Length + .write("client1") // Client Identifier + .flush() - //CONNACK - .read(0x20) // MQTT Control Packet type(2) - .read(0x02) // Remaining Length + // CONNACK + .read(0x20) // MQTT Control Packet type(2) + .read(0x02) // Remaining Length - //Connect Acknowledge Flags - .read(0x00) // Session Present Flag(0) + // Connect Acknowledge Flags + .read(0x00) // Session Present Flag(0) - //Connect Return code - .read(0x00) // Connection Accepted + // Connect Return code + .read(0x00) // Connection Accepted - //DISCONNECT - .write(0xE0) // MQTT Control Packet type(14) - .write(0x00) // Remaining Length - .closed(1000); + // DISCONNECT + .write(0xE0) // MQTT Control Packet type(14) + .write(0x00) // Remaining Length + .closed(1000); } @Test(timeout = 3000) public void testConnectWithInvalidWillQoS() throws Exception { RawClient.connect("127.0.0.1", 1883).isConnected() - //CONNECT - .write(0x10) //MQTT Control Packet type(1) - .write(0x13) // Remaining Length - .write(0x00, 0x04) // Protocol Name Length - .write("MQTT") // Protocol Name - .write(0x04) // The value of the Protocol Level field for the version 3.1.1 of the protocol is 4 (0x04) + // CONNECT + .write(0x10) // MQTT Control Packet type(1) + .write(0x13) // Remaining Length + .write(0x00, 0x04) // Protocol Name Length + .write("MQTT") // Protocol Name + .write(0x04) // The value of the Protocol Level field for the version 3.1.1 of the + // protocol is 4 (0x04) - //Connect Flags - //User Name Flag(0) - //Password Flag(0) - //Will Retain(0) - //Will QoS(11) - It MUST NOT be 3 (0x03). Server should close the connection. - //Will Flag(1) - //Clean Session(1) - .write(0x1E) // Reserved(0) - .write(0x00, 0x00) // Keep Alive + // Connect Flags + // User Name Flag(0) + // Password Flag(0) + // Will Retain(0) + // Will QoS(11) - It MUST NOT be 3 (0x03). Server should close the connection. + // Will Flag(1) + // Clean Session(1) + .write(0x1E) // Reserved(0) + .write(0x00, 0x00) // Keep Alive - // Payload - .write(0x00, 0x07) // Client Identifier Length - .write("client1") // Client Identifier - .flush() + // Payload + .write(0x00, 0x07) // Client Identifier Length + .write("client1") // Client Identifier + .flush() - .closed(1000); + .closed(1000); } @Ignore("Need to validate the test case.") @Test(timeout = 15000) public void testConnectWithWillFlagSetToZeroButWillQoSFlagSetToNonZero() throws Exception { RawClient.connect("127.0.0.1", 1883).isConnected() - // CONNECT - .write(0x10) // MQTT Control Packet type(1) - .write(0x12) // Remaining Length - .write(0x00, 0x04) // Protocol Name Length - .write("MQTT") // Protocol Name - .write(0x04) // The value of the Protocol Level field for the version 3.1.1 of the protocol is 4 (0x04) + // CONNECT + .write(0x10) // MQTT Control Packet type(1) + .write(0x12) // Remaining Length + .write(0x00, 0x04) // Protocol Name Length + .write("MQTT") // Protocol Name + .write(0x04) // The value of the Protocol Level field for the version 3.1.1 of the + // protocol is 4 (0x04) - // Connect Flags - // User Name Flag(0) - // Password Flag(0) - // Will Retain(0) - // Will QoS(01) - If the Will Flag is set to 0, then the Will QoS MUST be set to 0 - // Will Flag(0) - //Clean Session(1) - .write(0x0A) // Reserved(0) + // Connect Flags + // User Name Flag(0) + // Password Flag(0) + // Will Retain(0) + // Will QoS(01) - If the Will Flag is set to 0, then the Will QoS MUST be set to 0 + // Will Flag(0) + // Clean Session(1) + .write(0x0A) // Reserved(0) - .write(0x00, 0x00) // Keep Alive + .write(0x00, 0x00) // Keep Alive - // Payload - .write(0x00, 0x07) // Client Identifier Length - .write("client1") //Client Identifier + // Payload + .write(0x00, 0x07) // Client Identifier Length + .write("client1") // Client Identifier - //Server MUST close the Network Connection due to invalid Will QoS flag - .closed(); + // Server MUST close the Network Connection due to invalid Will QoS flag + .closed(); } } diff --git a/broker/src/test/java/io/moquette/spi/ClientSessionTest.java b/broker/src/test/java/io/moquette/spi/ClientSessionTest.java index 2275cc68..598728b9 100644 --- a/broker/src/test/java/io/moquette/spi/ClientSessionTest.java +++ b/broker/src/test/java/io/moquette/spi/ClientSessionTest.java @@ -1,3 +1,4 @@ + package io.moquette.spi; import io.moquette.spi.impl.MemoryStorageService; @@ -6,9 +7,7 @@ import io.moquette.spi.impl.subscriptions.SubscriptionsStore; import static io.netty.handler.codec.mqtt.MqttQoS.*; import org.junit.Before; import org.junit.Test; - import java.util.List; - import static org.junit.Assert.assertEquals; public class ClientSessionTest { @@ -42,7 +41,7 @@ public class ClientSessionTest { session1.subscribe(overrindingSubscription); store.add(overrindingSubscription.asClientTopicCouple()); - //Verify + // Verify List subscriptions = store.matches("/topic"); assertEquals(1, subscriptions.size()); Subscription sub = subscriptions.get(0); diff --git a/broker/src/test/java/io/moquette/spi/impl/BrokerInterceptorTest.java b/broker/src/test/java/io/moquette/spi/impl/BrokerInterceptorTest.java index 77c8a405..f1c02002 100644 --- a/broker/src/test/java/io/moquette/spi/impl/BrokerInterceptorTest.java +++ b/broker/src/test/java/io/moquette/spi/impl/BrokerInterceptorTest.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl; import io.moquette.interception.InterceptHandler; @@ -23,10 +24,8 @@ import io.netty.handler.codec.mqtt.MqttQoS; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; - import java.util.Arrays; import java.util.concurrent.atomic.AtomicInteger; - import static org.junit.Assert.assertEquals; import static org.mockito.Matchers.refEq; import static org.mockito.Mockito.mock; @@ -36,19 +35,23 @@ import static org.mockito.Mockito.verify; * @author Wagner Macedo */ public class BrokerInterceptorTest { + // value to check for changes after every notification private static final AtomicInteger n = new AtomicInteger(0); // Interceptor loaded with a custom InterceptHandler special for the tests private static final class MockObserver implements InterceptHandler { - @Override - public String getID() { - return "MockObserver"; - } - @Override - public Class[] getInterceptedMessageTypes() { - return InterceptHandler.ALL_MESSAGE_TYPES; - } + + @Override + public String getID() { + return "MockObserver"; + } + + @Override + public Class[] getInterceptedMessageTypes() { + return InterceptHandler.ALL_MESSAGE_TYPES; + } + @Override public void onConnect(InterceptConnectMessage msg) { n.set(40); @@ -79,13 +82,14 @@ public class BrokerInterceptorTest { n.set(80); } - @Override - public void onMessageAcknowledged( InterceptAcknowledgedMessage msg ) { - n.set(90); - } + @Override + public void onMessageAcknowledged(InterceptAcknowledgedMessage msg) { + n.set(90); + } } - private static final BrokerInterceptor interceptor = new BrokerInterceptor(Arrays.asList(new MockObserver())); + private static final BrokerInterceptor interceptor = new BrokerInterceptor( + Arrays.asList(new MockObserver())); @BeforeClass public static void beforeAllTests() { @@ -112,17 +116,17 @@ public class BrokerInterceptorTest { @Test public void testNotifyClientDisconnected() throws Exception { - interceptor.notifyClientDisconnected("cli1234","cli1234"); + interceptor.notifyClientDisconnected("cli1234", "cli1234"); interval(); assertEquals(50, n.get()); } @Test public void testNotifyTopicPublished() throws Exception { - interceptor.notifyTopicPublished(MessageBuilder.publish() - .qos(MqttQoS.AT_MOST_ONCE) - .payload("Hello".getBytes()) - .build(), "cli1234", "cli1234"); + interceptor.notifyTopicPublished( + MessageBuilder.publish().qos(MqttQoS.AT_MOST_ONCE).payload("Hello".getBytes()).build(), + "cli1234", + "cli1234"); interval(); assertEquals(60, n.get()); } @@ -163,7 +167,7 @@ public class BrokerInterceptorTest { interval(); // removeInterceptHandler() performs another interaction // TODO: fix this -// verifyNoMoreInteractions(interceptHandlerMock1); + // verifyNoMoreInteractions(interceptHandlerMock1); verify(interceptHandlerMock2).onSubscribe(refEq(new InterceptSubscribeMessage(subscription, "cli1235"))); } } diff --git a/broker/src/test/java/io/moquette/spi/impl/MemoryMessagesStore.java b/broker/src/test/java/io/moquette/spi/impl/MemoryMessagesStore.java index 968d9381..e48a2a46 100644 --- a/broker/src/test/java/io/moquette/spi/impl/MemoryMessagesStore.java +++ b/broker/src/test/java/io/moquette/spi/impl/MemoryMessagesStore.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl; import io.moquette.spi.IMessagesStore; @@ -20,9 +21,7 @@ import io.moquette.spi.IMatchingCondition; import io.moquette.spi.MessageGUID; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.util.*; - import static io.moquette.spi.impl.Utils.defaultGet; /** @@ -72,8 +71,10 @@ public class MemoryMessagesStore implements IMessagesStore { MessageGUID guid = new MessageGUID(UUID.randomUUID().toString()); storedMessage.setGuid(guid); m_persistentMessageStore.put(guid, storedMessage); - HashMap guids = (HashMap) defaultGet(m_messageToGuids, - storedMessage.getClientID(), new HashMap()); + HashMap guids = (HashMap) defaultGet( + m_messageToGuids, + storedMessage.getClientID(), + new HashMap()); guids.put(storedMessage.getMessageID(), guid); return guid; } diff --git a/broker/src/test/java/io/moquette/spi/impl/MemoryStorageService.java b/broker/src/test/java/io/moquette/spi/impl/MemoryStorageService.java index 639fe109..78fcedf0 100644 --- a/broker/src/test/java/io/moquette/spi/impl/MemoryStorageService.java +++ b/broker/src/test/java/io/moquette/spi/impl/MemoryStorageService.java @@ -13,21 +13,21 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl; import io.moquette.spi.IMessagesStore; import io.moquette.spi.ISessionsStore; import io.moquette.spi.MessageGUID; import io.moquette.spi.persistence.MemorySessionStore; - import java.util.HashMap; import java.util.Map; public class MemoryStorageService { - + private MemorySessionStore m_sessionsStore; private MemoryMessagesStore m_messagesStore; - + public void initStore() { Map> messageToGuids = new HashMap<>(); m_messagesStore = new MemoryMessagesStore(messageToGuids); diff --git a/broker/src/test/java/io/moquette/spi/impl/MockAuthenticator.java b/broker/src/test/java/io/moquette/spi/impl/MockAuthenticator.java index dee7753b..5f054dab 100644 --- a/broker/src/test/java/io/moquette/spi/impl/MockAuthenticator.java +++ b/broker/src/test/java/io/moquette/spi/impl/MockAuthenticator.java @@ -13,23 +13,23 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl; import java.util.Map; import java.util.Set; - import io.moquette.spi.security.IAuthenticator; /** * Test utility to implements authenticator instance. - * + * * @author andrea */ class MockAuthenticator implements IAuthenticator { private Set m_clientIds; private Map m_userPwds; - + MockAuthenticator(Set clientIds, Map userPwds) { m_clientIds = clientIds; m_userPwds = userPwds; @@ -47,5 +47,5 @@ class MockAuthenticator implements IAuthenticator { } return m_userPwds.get(username).equals(new String(password)); } - + } diff --git a/broker/src/test/java/io/moquette/spi/impl/MockReceiverChannel.java b/broker/src/test/java/io/moquette/spi/impl/MockReceiverChannel.java index 673febcc..fac2260c 100644 --- a/broker/src/test/java/io/moquette/spi/impl/MockReceiverChannel.java +++ b/broker/src/test/java/io/moquette/spi/impl/MockReceiverChannel.java @@ -13,11 +13,11 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl; import io.netty.handler.codec.mqtt.MqttMessage; import io.netty.util.AttributeKey; - import java.util.HashMap; import java.util.Map; @@ -25,6 +25,7 @@ import java.util.Map; * This a synchronous channel that avoid output ring buffer from Processor */ class MockReceiverChannel { + MqttMessage m_receivedMessage; private Map m_attributes = new HashMap<>(); diff --git a/broker/src/test/java/io/moquette/spi/impl/NettyChannelAssertions.java b/broker/src/test/java/io/moquette/spi/impl/NettyChannelAssertions.java index d2b91eab..9d8daeab 100644 --- a/broker/src/test/java/io/moquette/spi/impl/NettyChannelAssertions.java +++ b/broker/src/test/java/io/moquette/spi/impl/NettyChannelAssertions.java @@ -13,13 +13,13 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.handler.codec.mqtt.MqttConnAckMessage; import io.netty.handler.codec.mqtt.MqttConnectReturnCode; import io.netty.handler.codec.mqtt.MqttSubAckMessage; - import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.CONNECTION_ACCEPTED; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -48,10 +48,10 @@ class NettyChannelAssertions { assertEqualsConnAck(CONNECTION_ACCEPTED, channel.readOutbound()); } - static void assertEqualsSubAck(/*byte expectedCode,*/ Object subAck) { + static void assertEqualsSubAck(/* byte expectedCode, */ Object subAck) { assertTrue(subAck instanceof MqttSubAckMessage); - //SubAckMessage connAckMsg = (SubAckMessage) connAck; - //assertEquals(expectedCode, connAckMsg.getReturnCode()); + // SubAckMessage connAckMsg = (SubAckMessage) connAck; + // assertEquals(expectedCode, connAckMsg.getReturnCode()); } } diff --git a/broker/src/test/java/io/moquette/spi/impl/ProtocolProcessorTest.java b/broker/src/test/java/io/moquette/spi/impl/ProtocolProcessorTest.java index 825661b6..bdcb957a 100644 --- a/broker/src/test/java/io/moquette/spi/impl/ProtocolProcessorTest.java +++ b/broker/src/test/java/io/moquette/spi/impl/ProtocolProcessorTest.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl; import io.moquette.interception.InterceptHandler; @@ -30,10 +31,8 @@ import io.netty.channel.embedded.EmbeddedChannel; import io.netty.handler.codec.mqtt.*; import org.junit.Before; import org.junit.Test; - import java.util.*; import java.util.concurrent.BlockingQueue; - import static io.moquette.spi.impl.NettyChannelAssertions.assertConnAckAccepted; import static io.moquette.spi.impl.ProtocolProcessor.lowerQosToTheSubscriptionDesired; import static org.junit.Assert.*; @@ -44,19 +43,20 @@ import static org.mockito.Mockito.*; * @author andrea */ public class ProtocolProcessorTest { - final static String FAKE_CLIENT_ID = "FAKE_123"; - final static String FAKE_CLIENT_ID2 = "FAKE_456"; - final static String FAKE_PUBLISHER_ID = "Publisher"; - final static String FAKE_TOPIC = "/news"; - final static String BAD_FORMATTED_TOPIC = "#MQTTClient"; - final static String TEST_USER = "fakeuser"; - final static String TEST_PWD = "fakepwd"; - final static String EVIL_TEST_USER = "eviluser"; - final static String EVIL_TEST_PWD = "unsecret"; + static final String FAKE_CLIENT_ID = "FAKE_123"; + static final String FAKE_CLIENT_ID2 = "FAKE_456"; + static final String FAKE_PUBLISHER_ID = "Publisher"; + static final String FAKE_TOPIC = "/news"; + static final String BAD_FORMATTED_TOPIC = "#MQTTClient"; - final static List EMPTY_OBSERVERS = Collections.emptyList(); - final static BrokerInterceptor NO_OBSERVERS_INTERCEPTOR = new BrokerInterceptor(EMPTY_OBSERVERS); + static final String TEST_USER = "fakeuser"; + static final String TEST_PWD = "fakepwd"; + static final String EVIL_TEST_USER = "eviluser"; + static final String EVIL_TEST_PWD = "unsecret"; + + static final List EMPTY_OBSERVERS = Collections.emptyList(); + static final BrokerInterceptor NO_OBSERVERS_INTERCEPTOR = new BrokerInterceptor(EMPTY_OBSERVERS); EmbeddedChannel m_channel; MqttConnectMessage connMsg; @@ -69,26 +69,24 @@ public class ProtocolProcessorTest { @Before public void setUp() throws InterruptedException { - /*connMsg = new ConnectMessage(); - connMsg.setProtocolVersion((byte) 0x03); - - connMsg = MessageBuilder.connect() - .protocolVersion(MqttVersion.MQTT_3_1) - .clientId(FAKE_CLIENT_ID) - .cleanSession(true) - .build();*/ + /* + * connMsg = new ConnectMessage(); connMsg.setProtocolVersion((byte) 0x03); + * + * connMsg = MessageBuilder.connect() .protocolVersion(MqttVersion.MQTT_3_1) + * .clientId(FAKE_CLIENT_ID) .cleanSession(true) .build(); + */ m_channel = new EmbeddedChannel(); NettyUtils.clientID(m_channel, FAKE_CLIENT_ID); NettyUtils.cleanSession(m_channel, false); - //sleep to let the messaging batch processor to process the initEvent + // sleep to let the messaging batch processor to process the initEvent Thread.sleep(300); MemoryStorageService memStorage = new MemoryStorageService(); memStorage.initStore(); m_messagesStore = memStorage.messagesStore(); m_sessionStore = memStorage.sessionsStore(); - //m_messagesStore.initStore(); + // m_messagesStore.initStore(); Set clientIds = new HashSet<>(); clientIds.add(FAKE_CLIENT_ID); @@ -100,18 +98,23 @@ public class ProtocolProcessorTest { subscriptions = new SubscriptionsStore(); subscriptions.init(memStorage.sessionsStore()); m_processor = new ProtocolProcessor(); - m_processor.init(subscriptions, m_messagesStore, m_sessionStore, m_mockAuthenticator, true, - new PermitAllAuthorizator(), NO_OBSERVERS_INTERCEPTOR); + m_processor.init( + subscriptions, + m_messagesStore, + m_sessionStore, + m_mockAuthenticator, + true, + new PermitAllAuthorizator(), + NO_OBSERVERS_INTERCEPTOR); } - @Test public void testPublishToItself() throws InterruptedException { - final Subscription subscription = new Subscription(FAKE_CLIENT_ID, - FAKE_TOPIC, MqttQoS.AT_MOST_ONCE); + final Subscription subscription = new Subscription(FAKE_CLIENT_ID, FAKE_TOPIC, MqttQoS.AT_MOST_ONCE); - //subscriptions.matches(topic) redefine the method to return true + // subscriptions.matches(topic) redefine the method to return true SubscriptionsStore subs = new SubscriptionsStore() { + @Override public List matches(String topic) { if (topic.equals(FAKE_TOPIC)) { @@ -121,45 +124,43 @@ public class ProtocolProcessorTest { } } }; - - //simulate a connect that register a clientID to an IoSession + + // simulate a connect that register a clientID to an IoSession MemoryStorageService storageService = new MemoryStorageService(); storageService.initStore(); subs.init(storageService.sessionsStore()); - m_processor.init(subs, m_messagesStore, m_sessionStore, null, true, new PermitAllAuthorizator(), NO_OBSERVERS_INTERCEPTOR); - MqttConnectMessage connectMessage = MessageBuilder.connect() - .protocolVersion(MqttVersion.MQTT_3_1) - .clientId(FAKE_CLIENT_ID) - .cleanSession(true) - .build(); + m_processor.init( + subs, + m_messagesStore, + m_sessionStore, + null, + true, + new PermitAllAuthorizator(), + NO_OBSERVERS_INTERCEPTOR); + MqttConnectMessage connectMessage = MessageBuilder.connect().protocolVersion(MqttVersion.MQTT_3_1) + .clientId(FAKE_CLIENT_ID).cleanSession(true).build(); m_processor.processConnect(m_channel, connectMessage); - - - //Exercise - MqttPublishMessage msg = MessageBuilder.publish() - .topicName(FAKE_TOPIC) - .qos(MqttQoS.AT_MOST_ONCE) - .retained(false) - .payload("Hello".getBytes()) - .build(); + + // Exercise + MqttPublishMessage msg = MessageBuilder.publish().topicName(FAKE_TOPIC).qos(MqttQoS.AT_MOST_ONCE) + .retained(false).payload("Hello".getBytes()).build(); NettyUtils.userName(m_channel, "FakeCLI"); m_processor.processPublish(m_channel, msg); - //Verify + // Verify assertNotNull(m_channel.readOutbound()); - //TODO check received message attributes + // TODO check received message attributes } - + @Test public void testPublishToMultipleSubscribers() throws InterruptedException { - final Subscription subscription = new Subscription(FAKE_CLIENT_ID, - FAKE_TOPIC, MqttQoS.AT_MOST_ONCE); - final Subscription subscriptionClient2 = new Subscription(FAKE_CLIENT_ID2, - FAKE_TOPIC, MqttQoS.AT_MOST_ONCE); + final Subscription subscription = new Subscription(FAKE_CLIENT_ID, FAKE_TOPIC, MqttQoS.AT_MOST_ONCE); + final Subscription subscriptionClient2 = new Subscription(FAKE_CLIENT_ID2, FAKE_TOPIC, MqttQoS.AT_MOST_ONCE); - //subscriptions.matches(topic) redefine the method to return true + // subscriptions.matches(topic) redefine the method to return true SubscriptionsStore subs = new SubscriptionsStore() { + @Override public List matches(String topic) { if (topic.equals(FAKE_TOPIC)) { @@ -169,44 +170,40 @@ public class ProtocolProcessorTest { } } }; - - //simulate a connect that register a clientID to an IoSession + + // simulate a connect that register a clientID to an IoSession MemoryStorageService storageService = new MemoryStorageService(); storageService.initStore(); subs.init(storageService.sessionsStore()); - m_processor.init(subs, m_messagesStore, m_sessionStore, null, true, new PermitAllAuthorizator(), NO_OBSERVERS_INTERCEPTOR); + m_processor.init( + subs, + m_messagesStore, + m_sessionStore, + null, + true, + new PermitAllAuthorizator(), + NO_OBSERVERS_INTERCEPTOR); EmbeddedChannel firstReceiverChannel = new EmbeddedChannel(); - MqttConnectMessage connectMessage = MessageBuilder.connect() - .protocolVersion(MqttVersion.MQTT_3_1) - .clientId(FAKE_CLIENT_ID) - .cleanSession(true) - .build(); + MqttConnectMessage connectMessage = MessageBuilder.connect().protocolVersion(MqttVersion.MQTT_3_1) + .clientId(FAKE_CLIENT_ID).cleanSession(true).build(); m_processor.processConnect(firstReceiverChannel, connectMessage); assertConnAckAccepted(firstReceiverChannel); - - //connect the second fake subscriber + + // connect the second fake subscriber EmbeddedChannel secondReceiverChannel = new EmbeddedChannel(); - MqttConnectMessage connectMessage2 = MessageBuilder.connect() - .protocolVersion(MqttVersion.MQTT_3_1) - .clientId(FAKE_CLIENT_ID2) - .cleanSession(true) - .build(); + MqttConnectMessage connectMessage2 = MessageBuilder.connect().protocolVersion(MqttVersion.MQTT_3_1) + .clientId(FAKE_CLIENT_ID2).cleanSession(true).build(); m_processor.processConnect(secondReceiverChannel, connectMessage2); assertConnAckAccepted(secondReceiverChannel); - //Exercise - MqttPublishMessage msg = MessageBuilder.publish() - .topicName(FAKE_TOPIC) - .qos(MqttQoS.AT_MOST_ONCE) - .retained(false) - .payload("Hello".getBytes()) - .build(); + // Exercise + MqttPublishMessage msg = MessageBuilder.publish().topicName(FAKE_TOPIC).qos(MqttQoS.AT_MOST_ONCE) + .retained(false).payload("Hello".getBytes()).build(); NettyUtils.userName(m_channel, "FakeCLI"); m_processor.processPublish(m_channel, msg); - - //Verify + // Verify firstReceiverChannel.flush(); MqttPublishMessage pub2FirstSubscriber = firstReceiverChannel.readOutbound(); assertNotNull(pub2FirstSubscriber); @@ -222,15 +219,13 @@ public class ProtocolProcessorTest { @Test public void testSubscribe() { - MqttSubscribeMessage msg = MessageBuilder.subscribe() - .addSubscription(MqttQoS.AT_MOST_ONCE, FAKE_TOPIC) - .messageId(10) - .build(); - //Exercise + MqttSubscribeMessage msg = MessageBuilder.subscribe().addSubscription(MqttQoS.AT_MOST_ONCE, FAKE_TOPIC) + .messageId(10).build(); + // Exercise m_sessionStore.createNewSession(FAKE_CLIENT_ID, false); m_processor.processSubscribe(m_channel, msg); - //Verify + // Verify assertTrue(m_channel.readOutbound() instanceof MqttSubAckMessage); Subscription expectedSubscription = new Subscription(FAKE_CLIENT_ID, FAKE_TOPIC, MqttQoS.AT_MOST_ONCE); assertTrue(subscriptions.contains(expectedSubscription)); @@ -243,19 +238,23 @@ public class ProtocolProcessorTest { IAuthorizator mockAuthorizator = mock(IAuthorizator.class); when(mockAuthorizator.canRead(eq(FAKE_TOPIC), eq(fakeUserName), eq(FAKE_CLIENT_ID))).thenReturn(false); - m_processor.init(subscriptions, m_messagesStore, m_sessionStore, m_mockAuthenticator, true, - mockAuthorizator, NO_OBSERVERS_INTERCEPTOR); + m_processor.init( + subscriptions, + m_messagesStore, + m_sessionStore, + m_mockAuthenticator, + true, + mockAuthorizator, + NO_OBSERVERS_INTERCEPTOR); - //Exercise - MqttSubscribeMessage msg = MessageBuilder.subscribe() - .addSubscription(MqttQoS.AT_MOST_ONCE, FAKE_TOPIC) - .messageId(10) - .build(); + // Exercise + MqttSubscribeMessage msg = MessageBuilder.subscribe().addSubscription(MqttQoS.AT_MOST_ONCE, FAKE_TOPIC) + .messageId(10).build(); m_sessionStore.createNewSession(FAKE_CLIENT_ID, false); m_processor.processSubscribe(m_channel, msg); - //Verify + // Verify Object ackMsg = m_channel.readOutbound(); assertTrue(ackMsg instanceof MqttSubAckMessage); MqttSubAckMessage subAckMsg = (MqttSubAckMessage) ackMsg; @@ -270,39 +269,34 @@ public class ProtocolProcessorTest { @Test public void testDoubleSubscribe() { - MqttSubscribeMessage msg = MessageBuilder.subscribe() - .addSubscription(MqttQoS.AT_MOST_ONCE, FAKE_TOPIC) - .messageId(10) - .build(); + MqttSubscribeMessage msg = MessageBuilder.subscribe().addSubscription(MqttQoS.AT_MOST_ONCE, FAKE_TOPIC) + .messageId(10).build(); m_sessionStore.createNewSession(FAKE_CLIENT_ID, false); assertEquals(0, subscriptions.size()); - - m_processor.processSubscribe(m_channel, msg); - - //Exercise + m_processor.processSubscribe(m_channel, msg); - //Verify + // Exercise + m_processor.processSubscribe(m_channel, msg); + + // Verify assertEquals(1, subscriptions.size()); Subscription expectedSubscription = new Subscription(FAKE_CLIENT_ID, FAKE_TOPIC, MqttQoS.AT_MOST_ONCE); assertTrue(subscriptions.contains(expectedSubscription)); } - @Test public void testSubscribeWithBadFormattedTopic() { - MqttSubscribeMessage msg = MessageBuilder.subscribe() - .addSubscription(MqttQoS.AT_MOST_ONCE, BAD_FORMATTED_TOPIC) - .messageId(10) - .build(); + MqttSubscribeMessage msg = MessageBuilder.subscribe().addSubscription(MqttQoS.AT_MOST_ONCE, BAD_FORMATTED_TOPIC) + .messageId(10).build(); m_sessionStore.createNewSession(FAKE_CLIENT_ID, false); assertEquals(0, subscriptions.size()); - //Exercise + // Exercise m_processor.processSubscribe(m_channel, msg); - //Verify + // Verify assertEquals(0, subscriptions.size()); Object recvSubAckMessage = m_channel.readOutbound(); assertTrue(recvSubAckMessage instanceof MqttSubAckMessage); @@ -311,30 +305,27 @@ public class ProtocolProcessorTest { /* * Check topicFilter is a valid MQTT topic filter (issue 68) - * */ + */ @Test public void testUnsubscribeWithBadFormattedTopic() { - MqttUnsubscribeMessage msg = MessageBuilder.unsubscribe() - .addTopicFilter(BAD_FORMATTED_TOPIC) - .messageId(1) + MqttUnsubscribeMessage msg = MessageBuilder.unsubscribe().addTopicFilter(BAD_FORMATTED_TOPIC).messageId(1) .build(); - //Exercise + // Exercise m_processor.processUnsubscribe(m_channel, msg); - //Verify + // Verify assertFalse("If client unsubscribe with bad topic than channel must be closed", m_channel.isOpen()); } - @Test public void testPublishOfRetainedMessage_afterNewSubscription() throws Exception { - //simulate a connect that register a clientID to an IoSession - final Subscription subscription = new Subscription(FAKE_PUBLISHER_ID, - FAKE_TOPIC, MqttQoS.AT_MOST_ONCE); + // simulate a connect that register a clientID to an IoSession + final Subscription subscription = new Subscription(FAKE_PUBLISHER_ID, FAKE_TOPIC, MqttQoS.AT_MOST_ONCE); - //subscriptions.matches(topic) redefine the method to return true + // subscriptions.matches(topic) redefine the method to return true SubscriptionsStore subs = new SubscriptionsStore() { + @Override public List matches(String topic) { if (topic.equals(FAKE_TOPIC)) { @@ -348,36 +339,34 @@ public class ProtocolProcessorTest { storageService.initStore(); subs.init(storageService.sessionsStore()); - //simulate a connect that register a clientID to an IoSession - m_processor.init(subs, m_messagesStore, m_sessionStore, null, true, new PermitAllAuthorizator(), NO_OBSERVERS_INTERCEPTOR); - MqttConnectMessage connectMessage = MessageBuilder.connect() - .clientId(FAKE_PUBLISHER_ID) - .protocolVersion(MqttVersion.MQTT_3_1) - .cleanSession(true) - .build(); + // simulate a connect that register a clientID to an IoSession + m_processor.init( + subs, + m_messagesStore, + m_sessionStore, + null, + true, + new PermitAllAuthorizator(), + NO_OBSERVERS_INTERCEPTOR); + MqttConnectMessage connectMessage = MessageBuilder.connect().clientId(FAKE_PUBLISHER_ID) + .protocolVersion(MqttVersion.MQTT_3_1).cleanSession(true).build(); m_processor.processConnect(m_channel, connectMessage); assertConnAckAccepted(m_channel); - MqttPublishMessage pubmsg = MessageBuilder.publish() - .topicName(FAKE_TOPIC) - .qos(MqttQoS.AT_MOST_ONCE) - .payload("Hello".getBytes()) - .retained(true) - .build(); + MqttPublishMessage pubmsg = MessageBuilder.publish().topicName(FAKE_TOPIC).qos(MqttQoS.AT_MOST_ONCE) + .payload("Hello".getBytes()).retained(true).build(); NettyUtils.clientID(m_channel, FAKE_PUBLISHER_ID); m_processor.processPublish(m_channel, pubmsg); NettyUtils.cleanSession(m_channel, false); - //Exercise - MqttSubscribeMessage msg = MessageBuilder.subscribe() - .messageId(10) - .addSubscription(MqttQoS.AT_MOST_ONCE, "#") + // Exercise + MqttSubscribeMessage msg = MessageBuilder.subscribe().messageId(10).addSubscription(MqttQoS.AT_MOST_ONCE, "#") .build(); m_processor.processSubscribe(m_channel, msg); - //Verify - //wait the latch + // Verify + // wait the latch Object pubMessage = m_channel.readOutbound(); assertNotNull(pubMessage); assertTrue(pubMessage instanceof MqttPublishMessage); @@ -396,23 +385,28 @@ public class ProtocolProcessorTest { retainedMessage.setClientID(FAKE_PUBLISHER_ID); m_messagesStore.storePublishForFuture(retainedMessage); - m_processor.init(subs, m_messagesStore, m_sessionStore, null, true, new PermitAllAuthorizator(), NO_OBSERVERS_INTERCEPTOR); + m_processor.init( + subs, + m_messagesStore, + m_sessionStore, + null, + true, + new PermitAllAuthorizator(), + NO_OBSERVERS_INTERCEPTOR); - MqttConnectMessage connectMessage = MessageBuilder.connect() - .clientId(FAKE_PUBLISHER_ID) - .protocolVersion(MqttVersion.MQTT_3_1) - .build(); + MqttConnectMessage connectMessage = MessageBuilder.connect().clientId(FAKE_PUBLISHER_ID) + .protocolVersion(MqttVersion.MQTT_3_1).build(); m_processor.processConnect(m_channel, connectMessage); - //Verify no messages are still stored + // Verify no messages are still stored BlockingQueue messages = m_sessionStore.queue(FAKE_PUBLISHER_ID); assertTrue(messages.isEmpty()); } - + @Test public void publishNoPublishToInactiveSession() { - //create an inactive session for Subscriber + // create an inactive session for Subscriber m_sessionStore.createNewSession("Subscriber", false); SubscriptionsStore mockedSubscriptions = mock(SubscriptionsStore.class); @@ -420,69 +414,61 @@ public class ProtocolProcessorTest { List inactiveSubscriptions = Collections.singletonList(inactiveSub); when(mockedSubscriptions.matches(eq("/topic"))).thenReturn(inactiveSubscriptions); m_processor = new ProtocolProcessor(); - m_processor.init(mockedSubscriptions, m_messagesStore, m_sessionStore, null, true, new PermitAllAuthorizator(), + m_processor.init( + mockedSubscriptions, + m_messagesStore, + m_sessionStore, + null, + true, + new PermitAllAuthorizator(), NO_OBSERVERS_INTERCEPTOR); - - //Exercise - MqttPublishMessage msg = MessageBuilder.publish() - .topicName("/topic") - .qos(MqttQoS.AT_MOST_ONCE) - .payload("Hello".getBytes()) - .retained(true) - .build(); + + // Exercise + MqttPublishMessage msg = MessageBuilder.publish().topicName("/topic").qos(MqttQoS.AT_MOST_ONCE) + .payload("Hello".getBytes()).retained(true).build(); NettyUtils.clientID(m_channel, "Publisher"); m_processor.processPublish(m_channel, msg); - //Verify no message is received + // Verify no message is received assertNull(m_channel.readOutbound()); } - + /** - * Verify that receiving a publish with retained message and with Q0S = 0 - * clean the existing retained messages for that topic. + * Verify that receiving a publish with retained message and with Q0S = 0 clean the existing + * retained messages for that topic. */ @Test public void testCleanRetainedStoreAfterAQoS0AndRetainedTrue() { - //force a connect - connMsg = MessageBuilder.connect() - .protocolVersion(MqttVersion.MQTT_3_1) - .clientId("Publisher") - .cleanSession(true) - .build(); + // force a connect + connMsg = MessageBuilder.connect().protocolVersion(MqttVersion.MQTT_3_1).clientId("Publisher") + .cleanSession(true).build(); m_processor.processConnect(m_channel, connMsg); - //prepare and existing retained store + // prepare and existing retained store NettyUtils.clientID(m_channel, "Publisher"); - MqttPublishMessage msg = MessageBuilder.publish() - .topicName(FAKE_TOPIC) - .qos(MqttQoS.AT_LEAST_ONCE) - .payload("Hello".getBytes()) - .retained(true) - .messageId(100) - .build(); + MqttPublishMessage msg = MessageBuilder.publish().topicName(FAKE_TOPIC).qos(MqttQoS.AT_LEAST_ONCE) + .payload("Hello".getBytes()).retained(true).messageId(100).build(); m_processor.processPublish(m_channel, msg); Collection messages = m_messagesStore.searchMatching(new IMatchingCondition() { + public boolean match(String key) { - return SubscriptionsStore.matchTopics(key, FAKE_TOPIC); + return SubscriptionsStore.matchTopics(key, FAKE_TOPIC); } }); assertFalse(messages.isEmpty()); - //Exercise - MqttPublishMessage cleanPubMsg = MessageBuilder.publish() - .topicName(FAKE_TOPIC) - .qos(MqttQoS.AT_MOST_ONCE) - .payload("Hello".getBytes()) - .retained(true) - .build(); + // Exercise + MqttPublishMessage cleanPubMsg = MessageBuilder.publish().topicName(FAKE_TOPIC).qos(MqttQoS.AT_MOST_ONCE) + .payload("Hello".getBytes()).retained(true).build(); m_processor.processPublish(m_channel, cleanPubMsg); - - //Verify + + // Verify messages = m_messagesStore.searchMatching(new IMatchingCondition() { + public boolean match(String key) { - return SubscriptionsStore.matchTopics(key, FAKE_TOPIC); + return SubscriptionsStore.matchTopics(key, FAKE_TOPIC); } }); assertTrue(messages.isEmpty()); diff --git a/broker/src/test/java/io/moquette/spi/impl/ProtocolProcessor_CONNECT_Test.java b/broker/src/test/java/io/moquette/spi/impl/ProtocolProcessor_CONNECT_Test.java index ff8f7fa2..af73bb60 100644 --- a/broker/src/test/java/io/moquette/spi/impl/ProtocolProcessor_CONNECT_Test.java +++ b/broker/src/test/java/io/moquette/spi/impl/ProtocolProcessor_CONNECT_Test.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl; import io.moquette.server.netty.MessageBuilder; @@ -30,12 +31,10 @@ import io.netty.handler.codec.mqtt.MqttSubscribeMessage; import io.netty.handler.codec.mqtt.MqttVersion; import org.junit.Before; import org.junit.Test; - import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; - import static io.moquette.spi.impl.NettyChannelAssertions.assertEqualsConnAck; import static io.moquette.spi.impl.NettyChannelAssertions.assertEqualsSubAck; import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.*; @@ -59,19 +58,17 @@ public class ProtocolProcessor_CONNECT_Test { @Before public void setUp() throws InterruptedException { - connMsg = MessageBuilder.connect() - .protocolVersion(MqttVersion.MQTT_3_1) - .cleanSession(true); + connMsg = MessageBuilder.connect().protocolVersion(MqttVersion.MQTT_3_1).cleanSession(true); m_session = new EmbeddedChannel(); - //sleep to let the messaging batch processor to process the initEvent + // sleep to let the messaging batch processor to process the initEvent Thread.sleep(300); MemoryStorageService memStorage = new MemoryStorageService(); memStorage.initStore(); m_messagesStore = memStorage.messagesStore(); m_sessionStore = memStorage.sessionsStore(); - //m_messagesStore.initStore(); + // m_messagesStore.initStore(); Set clientIds = new HashSet<>(); clientIds.add(ProtocolProcessorTest.FAKE_CLIENT_ID); @@ -82,284 +79,273 @@ public class ProtocolProcessor_CONNECT_Test { subscriptions = new SubscriptionsStore(); subscriptions.init(m_sessionStore); m_processor = new ProtocolProcessor(); - m_processor.init(subscriptions, m_messagesStore, m_sessionStore, m_mockAuthenticator, true, - new PermitAllAuthorizator(), ProtocolProcessorTest.NO_OBSERVERS_INTERCEPTOR); + m_processor.init( + subscriptions, + m_messagesStore, + m_sessionStore, + m_mockAuthenticator, + true, + new PermitAllAuthorizator(), + ProtocolProcessorTest.NO_OBSERVERS_INTERCEPTOR); } -// @Test -// public void testHandleConnect_BadProtocol() { -// connMsg.setProtocolVersion((byte) 0x02); -// -// //Exercise -// m_processor.processConnect(m_session, connMsg); -// -// //Verify -// assertEqualsConnAck(UNNACEPTABLE_PROTOCOL_VERSION, m_session.readOutbound()); -// assertFalse("Connection should be closed by the broker.", m_session.isOpen()); -// } + // @Test + // public void testHandleConnect_BadProtocol() { + // connMsg.setProtocolVersion((byte) 0x02); + // + // //Exercise + // m_processor.processConnect(m_session, connMsg); + // + // //Verify + // assertEqualsConnAck(UNNACEPTABLE_PROTOCOL_VERSION, m_session.readOutbound()); + // assertFalse("Connection should be closed by the broker.", m_session.isOpen()); + // } @Test public void testConnect_badClientID() { connMsg.clientId("extremely_long_clientID_greater_than_23").build(); - //Exercise + // Exercise m_processor.processConnect(m_session, connMsg.clientId("extremely_long_clientID_greater_than_23").build()); - //Verify + // Verify assertEqualsConnAck(CONNECTION_ACCEPTED, m_session.readOutbound()); } @Test public void testWill() { - MqttConnectMessage msg = connMsg - .clientId(ProtocolProcessorTest.FAKE_CLIENT_ID) - .willFlag(true) - .willTopic("topic") - .willMessage("Topic message") - .build(); + MqttConnectMessage msg = connMsg.clientId(ProtocolProcessorTest.FAKE_CLIENT_ID).willFlag(true) + .willTopic("topic").willMessage("Topic message").build(); - //Exercise - //m_handler.setMessaging(mockedMessaging); + // Exercise + // m_handler.setMessaging(mockedMessaging); m_processor.processConnect(m_session, msg); - //Verify + // Verify assertEqualsConnAck(CONNECTION_ACCEPTED, m_session.readOutbound()); assertTrue("Connection is accepted and therefore should remain open.", m_session.isOpen()); - //TODO verify the call - /*verify(mockedMessaging).publish(eq("topic"), eq("Topic message".getBytes()), - any(AbstractMessage.QOSType.class), anyBoolean(), eq("123"), any(IoSession.class));*/ + // TODO verify the call + /* + * verify(mockedMessaging).publish(eq("topic"), eq("Topic message".getBytes()), + * any(AbstractMessage.QOSType.class), anyBoolean(), eq("123"), any(IoSession.class)); + */ } @Test public void validAuthentication() { - MqttConnectMessage msg = connMsg - .clientId(ProtocolProcessorTest.FAKE_CLIENT_ID) - .hasUser() - .hasPassword() - .username(ProtocolProcessorTest.TEST_USER) - .password(ProtocolProcessorTest.TEST_PWD) - .build(); + MqttConnectMessage msg = connMsg.clientId(ProtocolProcessorTest.FAKE_CLIENT_ID).hasUser().hasPassword() + .username(ProtocolProcessorTest.TEST_USER).password(ProtocolProcessorTest.TEST_PWD).build(); - //Exercise + // Exercise m_processor.processConnect(m_session, msg); - //Verify + // Verify assertEqualsConnAck(CONNECTION_ACCEPTED, m_session.readOutbound()); assertTrue("Connection is accepted and therefore should remain open.", m_session.isOpen()); } @Test public void noPasswdAuthentication() { - MqttConnectMessage msg = connMsg - .clientId(ProtocolProcessorTest.FAKE_CLIENT_ID) - .hasUser() - .username(ProtocolProcessorTest.TEST_USER) - .build(); + MqttConnectMessage msg = connMsg.clientId(ProtocolProcessorTest.FAKE_CLIENT_ID).hasUser() + .username(ProtocolProcessorTest.TEST_USER).build(); - //Exercise + // Exercise m_processor.processConnect(m_session, msg); - //Verify + // Verify assertEqualsConnAck(CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD, m_session.readOutbound()); assertFalse("Connection should be closed by the broker.", m_session.isOpen()); } @Test public void invalidAuthentication() { - MqttConnectMessage msg = connMsg - .clientId(ProtocolProcessorTest.FAKE_CLIENT_ID) - .hasUser() - .hasPassword() - .username(ProtocolProcessorTest.TEST_USER + "_fake") - .password(ProtocolProcessorTest.TEST_PWD) - .build(); + MqttConnectMessage msg = connMsg.clientId(ProtocolProcessorTest.FAKE_CLIENT_ID).hasUser().hasPassword() + .username(ProtocolProcessorTest.TEST_USER + "_fake").password(ProtocolProcessorTest.TEST_PWD).build(); - //Exercise + // Exercise m_processor.processConnect(m_session, msg); - //Verify + // Verify assertEqualsConnAck(CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD, m_session.readOutbound()); assertFalse("Connection should be closed by the broker.", m_session.isOpen()); } @Test public void prohibitAnonymousClient() { - MqttConnectMessage msg = connMsg - .clientId(ProtocolProcessorTest.FAKE_CLIENT_ID) - .build(); - m_processor.init(subscriptions, m_messagesStore, m_sessionStore, m_mockAuthenticator, false, - new PermitAllAuthorizator(), ProtocolProcessorTest.NO_OBSERVERS_INTERCEPTOR); + MqttConnectMessage msg = connMsg.clientId(ProtocolProcessorTest.FAKE_CLIENT_ID).build(); + m_processor.init( + subscriptions, + m_messagesStore, + m_sessionStore, + m_mockAuthenticator, + false, + new PermitAllAuthorizator(), + ProtocolProcessorTest.NO_OBSERVERS_INTERCEPTOR); - //Exercise + // Exercise m_processor.processConnect(m_session, msg); - //Verify + // Verify assertEqualsConnAck(CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD, m_session.readOutbound()); assertFalse("Connection should be closed by the broker.", m_session.isOpen()); } @Test public void prohibitAnonymousClient_providingUsername() { - MqttConnectMessage msg = connMsg - .clientId(ProtocolProcessorTest.FAKE_CLIENT_ID) - .hasUser() - .username(ProtocolProcessorTest.TEST_USER + "_fake") - .build(); - m_processor.init(subscriptions, m_messagesStore, m_sessionStore, m_mockAuthenticator, false, - new PermitAllAuthorizator(), ProtocolProcessorTest.NO_OBSERVERS_INTERCEPTOR); + MqttConnectMessage msg = connMsg.clientId(ProtocolProcessorTest.FAKE_CLIENT_ID).hasUser() + .username(ProtocolProcessorTest.TEST_USER + "_fake").build(); + m_processor.init( + subscriptions, + m_messagesStore, + m_sessionStore, + m_mockAuthenticator, + false, + new PermitAllAuthorizator(), + ProtocolProcessorTest.NO_OBSERVERS_INTERCEPTOR); - //Exercise + // Exercise m_processor.processConnect(m_session, msg); - //Verify + // Verify assertEqualsConnAck(CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD, m_session.readOutbound()); assertFalse("Connection should be closed by the broker.", m_session.isOpen()); } @Test public void acceptAnonymousClient() { - MqttConnectMessage msg = connMsg - .clientId(ProtocolProcessorTest.FAKE_CLIENT_ID) - .build(); - m_processor.init(subscriptions, m_messagesStore, m_sessionStore, m_mockAuthenticator, true, - new PermitAllAuthorizator(), ProtocolProcessorTest.NO_OBSERVERS_INTERCEPTOR); + MqttConnectMessage msg = connMsg.clientId(ProtocolProcessorTest.FAKE_CLIENT_ID).build(); + m_processor.init( + subscriptions, + m_messagesStore, + m_sessionStore, + m_mockAuthenticator, + true, + new PermitAllAuthorizator(), + ProtocolProcessorTest.NO_OBSERVERS_INTERCEPTOR); - //Exercise + // Exercise m_processor.processConnect(m_session, msg); - //Verify + // Verify assertEqualsConnAck(CONNECTION_ACCEPTED, m_session.readOutbound()); assertTrue("Connection is accepted and therefore should remain open.", m_session.isOpen()); } @Test public void connectWithCleanSessionUpdateClientSession() throws InterruptedException { - m_processor.init(subscriptions, m_messagesStore, m_sessionStore, m_mockAuthenticator, true, - new PermitAllAuthorizator(), ProtocolProcessorTest.NO_OBSERVERS_INTERCEPTOR); + m_processor.init( + subscriptions, + m_messagesStore, + m_sessionStore, + m_mockAuthenticator, + true, + new PermitAllAuthorizator(), + ProtocolProcessorTest.NO_OBSERVERS_INTERCEPTOR); - //first connect with clean session true - MqttConnectMessage msg = connMsg - .clientId(ProtocolProcessorTest.FAKE_CLIENT_ID) - .cleanSession(true) - .build(); + // first connect with clean session true + MqttConnectMessage msg = connMsg.clientId(ProtocolProcessorTest.FAKE_CLIENT_ID).cleanSession(true).build(); m_processor.processConnect(m_session, msg); assertEqualsConnAck(CONNECTION_ACCEPTED, m_session.readOutbound()); m_processor.processDisconnect(m_session); assertFalse(m_session.isOpen()); - //second connect with clean session false + // second connect with clean session false m_session = new EmbeddedChannel(); - MqttConnectMessage secondConnMsg = MessageBuilder.connect() - .clientId(ProtocolProcessorTest.FAKE_CLIENT_ID) - .protocolVersion(MqttVersion.MQTT_3_1) - .build(); + MqttConnectMessage secondConnMsg = MessageBuilder.connect().clientId(ProtocolProcessorTest.FAKE_CLIENT_ID) + .protocolVersion(MqttVersion.MQTT_3_1).build(); m_processor.processConnect(m_session, secondConnMsg); assertEqualsConnAck(CONNECTION_ACCEPTED, m_session.readOutbound()); - //Verify client session is clean false + // Verify client session is clean false ClientSession session = m_sessionStore.sessionForClient(ProtocolProcessorTest.FAKE_CLIENT_ID); assertFalse(session.isCleanSession()); - //Verify - //assertEqualsConnAck(CONNECTION_ACCEPTED, m_session.readOutbound()); + // Verify + // assertEqualsConnAck(CONNECTION_ACCEPTED, m_session.readOutbound()); } @Test public void connectWithSameClientIDBadCredentialsDoesntDropExistingClient() { - //Connect a client1 - MqttConnectMessage msg = connMsg - .clientId(ProtocolProcessorTest.FAKE_CLIENT_ID) - .hasUser() - .hasPassword() - .username(ProtocolProcessorTest.TEST_USER) - .password(ProtocolProcessorTest.TEST_PWD) - .build(); + // Connect a client1 + MqttConnectMessage msg = connMsg.clientId(ProtocolProcessorTest.FAKE_CLIENT_ID).hasUser().hasPassword() + .username(ProtocolProcessorTest.TEST_USER).password(ProtocolProcessorTest.TEST_PWD).build(); m_processor.processConnect(m_session, msg); assertEqualsConnAck(CONNECTION_ACCEPTED, m_session.readOutbound()); - //create another connect same clientID but with bad credentials - MqttConnectMessage evilClientConnMsg = MessageBuilder.connect(). - protocolVersion(MqttVersion.MQTT_3_1) - .clientId(ProtocolProcessorTest.FAKE_CLIENT_ID) - .hasUser().username(ProtocolProcessorTest.EVIL_TEST_USER) - .hasPassword().password(ProtocolProcessorTest.EVIL_TEST_PWD) - .build(); + // create another connect same clientID but with bad credentials + MqttConnectMessage evilClientConnMsg = MessageBuilder.connect().protocolVersion(MqttVersion.MQTT_3_1) + .clientId(ProtocolProcessorTest.FAKE_CLIENT_ID).hasUser().username(ProtocolProcessorTest.EVIL_TEST_USER) + .hasPassword().password(ProtocolProcessorTest.EVIL_TEST_PWD).build(); EmbeddedChannel evilSession = new EmbeddedChannel(); - //Exercise + // Exercise m_processor.processConnect(evilSession, evilClientConnMsg); - //Verify - //the evil client gets a not auth notification + // Verify + // the evil client gets a not auth notification assertEqualsConnAck(CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD, evilSession.readOutbound()); - //the good client remains connected + // the good client remains connected assertTrue(m_session.isOpen()); assertFalse(evilSession.isOpen()); } - @Test public void testConnAckContainsSessionPresentFlag() throws InterruptedException { - MqttConnectMessage msg = connMsg - .clientId(ProtocolProcessorTest.FAKE_CLIENT_ID) - .protocolVersion(MqttVersion.MQTT_3_1_1) - .build(); + MqttConnectMessage msg = connMsg.clientId(ProtocolProcessorTest.FAKE_CLIENT_ID) + .protocolVersion(MqttVersion.MQTT_3_1_1).build(); NettyUtils.clientID(m_session, ProtocolProcessorTest.FAKE_CLIENT_ID); NettyUtils.cleanSession(m_session, false); - //Connect a first time + // Connect a first time m_processor.processConnect(m_session, msg); - //disconnect + // disconnect m_processor.processDisconnect(m_session); - //Exercise, reconnect + // Exercise, reconnect EmbeddedChannel firstReceiverSession = new EmbeddedChannel(); m_processor.processConnect(firstReceiverSession, msg); - //Verify + // Verify assertEqualsConnAck(CONNECTION_ACCEPTED, firstReceiverSession.readOutbound()); assertTrue("Connection is accepted and therefore should remain open.", firstReceiverSession.isOpen()); } - @Test public void testMultipleReconnection() throws InterruptedException { - //connect with clean a false and subscribe to a topic - MqttConnectMessage msg = MessageBuilder.connect() - .clientId(ProtocolProcessorTest.FAKE_CLIENT_ID) - .protocolVersion(MqttVersion.MQTT_3_1_1) - .build(); + // connect with clean a false and subscribe to a topic + MqttConnectMessage msg = MessageBuilder.connect().clientId(ProtocolProcessorTest.FAKE_CLIENT_ID) + .protocolVersion(MqttVersion.MQTT_3_1_1).build(); m_processor.processConnect(m_session, msg); assertEqualsConnAck(CONNECTION_ACCEPTED, m_session.readOutbound()); assertTrue("Connection is accepted and therefore should remain open.", m_session.isOpen()); - //subscribe + // subscribe MqttSubscribeMessage subscribeMsg = MessageBuilder.subscribe() - .addSubscription(MqttQoS.AT_MOST_ONCE, ProtocolProcessorTest.FAKE_TOPIC) - .messageId(10) - .build(); + .addSubscription(MqttQoS.AT_MOST_ONCE, ProtocolProcessorTest.FAKE_TOPIC).messageId(10).build(); NettyUtils.clientID(m_session, ProtocolProcessorTest.FAKE_CLIENT_ID); NettyUtils.cleanSession(m_session, false); m_processor.processSubscribe(m_session, subscribeMsg); - Subscription expectedSubscription = new Subscription(ProtocolProcessorTest.FAKE_CLIENT_ID, ProtocolProcessorTest.FAKE_TOPIC, + Subscription expectedSubscription = new Subscription( + ProtocolProcessorTest.FAKE_CLIENT_ID, + ProtocolProcessorTest.FAKE_TOPIC, MqttQoS.AT_MOST_ONCE); assertTrue(subscriptions.contains(expectedSubscription)); assertEqualsSubAck(m_session.readOutbound()); - //disconnect + // disconnect m_processor.processDisconnect(m_session); assertFalse(m_session.isOpen()); - //reconnect clean session a false + // reconnect clean session a false m_session = new EmbeddedChannel(); m_processor.processConnect(m_session, msg); assertEqualsConnAck(CONNECTION_ACCEPTED, m_session.readOutbound()); assertTrue("Connection is accepted and therefore should remain open.", m_session.isOpen()); - //verify that the first subscription is still preserved + // verify that the first subscription is still preserved assertTrue(subscriptions.contains(expectedSubscription)); } @@ -367,18 +353,25 @@ public class ProtocolProcessor_CONNECT_Test { public void testZeroByteClientIdWithoutCleanSession() { // Allow zero byte client ids m_processor = new ProtocolProcessor(); - m_processor.init(subscriptions, m_messagesStore, m_sessionStore, m_mockAuthenticator, true, true, - new PermitAllAuthorizator(), ProtocolProcessorTest.NO_OBSERVERS_INTERCEPTOR); + m_processor.init( + subscriptions, + m_messagesStore, + m_sessionStore, + m_mockAuthenticator, + true, + true, + new PermitAllAuthorizator(), + ProtocolProcessorTest.NO_OBSERVERS_INTERCEPTOR); // Connect message without clean session set to true but client id is still null - MqttConnectMessage msg = MessageBuilder.connect() - .clientId(null) - .protocolVersion(MqttVersion.MQTT_3_1_1) + MqttConnectMessage msg = MessageBuilder.connect().clientId(null).protocolVersion(MqttVersion.MQTT_3_1_1) .build(); m_processor.processConnect(m_session, msg); - assertEqualsConnAck("Identifier should be rejected due to having clean session set to false.", - CONNECTION_REFUSED_IDENTIFIER_REJECTED, m_session.readOutbound()); + assertEqualsConnAck( + "Identifier should be rejected due to having clean session set to false.", + CONNECTION_REFUSED_IDENTIFIER_REJECTED, + m_session.readOutbound()); assertFalse("Connection should be closed by the broker.", m_session.isOpen()); } @@ -387,19 +380,26 @@ public class ProtocolProcessor_CONNECT_Test { public void testZeroByteClientIdWithCleanSession() { // Allow zero byte client ids m_processor = new ProtocolProcessor(); - m_processor.init(subscriptions, m_messagesStore, m_sessionStore, m_mockAuthenticator, true, true, - new PermitAllAuthorizator(), ProtocolProcessorTest.NO_OBSERVERS_INTERCEPTOR); + m_processor.init( + subscriptions, + m_messagesStore, + m_sessionStore, + m_mockAuthenticator, + true, + true, + new PermitAllAuthorizator(), + ProtocolProcessorTest.NO_OBSERVERS_INTERCEPTOR); // Connect message with clean session set to true and client id is null. - MqttConnectMessage msg = connMsg - .clientId(null) - .protocolVersion(MqttVersion.MQTT_3_1_1) - .cleanSession(true) + MqttConnectMessage msg = connMsg.clientId(null).protocolVersion(MqttVersion.MQTT_3_1_1).cleanSession(true) .build(); m_processor.processConnect(m_session, msg); - assertEqualsConnAck("Connection should be accepted. A unique clientid should be generated" + - " and clean session set to true.", CONNECTION_ACCEPTED, m_session.readOutbound()); + assertEqualsConnAck( + "Connection should be accepted. A unique clientid should be generated" + + " and clean session set to true.", + CONNECTION_ACCEPTED, + m_session.readOutbound()); assertTrue("Connection should be valid and open,", m_session.isOpen()); } @@ -407,15 +407,14 @@ public class ProtocolProcessor_CONNECT_Test { @Test public void testZeroByteClientIdNotAllowed() { // Connect message with clean session set to true and client id is null. - MqttConnectMessage msg = connMsg - .clientId(null) - .protocolVersion(MqttVersion.MQTT_3_1_1) - .cleanSession(true) + MqttConnectMessage msg = connMsg.clientId(null).protocolVersion(MqttVersion.MQTT_3_1_1).cleanSession(true) .build(); m_processor.processConnect(m_session, msg); - assertEqualsConnAck("Zero byte client identifiers are not allowed.", - CONNECTION_REFUSED_IDENTIFIER_REJECTED, m_session.readOutbound()); + assertEqualsConnAck( + "Zero byte client identifiers are not allowed.", + CONNECTION_REFUSED_IDENTIFIER_REJECTED, + m_session.readOutbound()); assertFalse("Connection should closed.", m_session.isOpen()); } diff --git a/broker/src/test/java/io/moquette/spi/impl/security/ACLFileParserTest.java b/broker/src/test/java/io/moquette/spi/impl/security/ACLFileParserTest.java index 4a58e2f7..c86bc577 100644 --- a/broker/src/test/java/io/moquette/spi/impl/security/ACLFileParserTest.java +++ b/broker/src/test/java/io/moquette/spi/impl/security/ACLFileParserTest.java @@ -13,19 +13,18 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl.security; import org.junit.Test; - import java.io.Reader; import java.io.StringReader; import java.text.ParseException; - import static org.junit.Assert.*; /** * @author andrea - * */ + */ public class ACLFileParserTest { @Test @@ -33,7 +32,7 @@ public class ACLFileParserTest { Reader conf = new StringReader(" "); AuthorizationsCollector authorizations = ACLFileParser.parse(conf); - //Verify + // Verify assertTrue(authorizations.isEmpty()); } @@ -42,7 +41,7 @@ public class ACLFileParserTest { Reader conf = new StringReader("#simple comment"); AuthorizationsCollector authorizations = ACLFileParser.parse(conf); - //Verify + // Verify assertTrue(authorizations.isEmpty()); } @@ -57,9 +56,9 @@ public class ACLFileParserTest { Reader conf = new StringReader("topic /weather/italy/anemometer"); AuthorizationsCollector authorizations = ACLFileParser.parse(conf); - //Verify + // Verify assertTrue(authorizations.canRead("/weather/italy/anemometer", "", "")); assertTrue(authorizations.canWrite("/weather/italy/anemometer", "", "")); } -} \ No newline at end of file +} diff --git a/broker/src/test/java/io/moquette/spi/impl/security/AuthorizationsCollectorTest.java b/broker/src/test/java/io/moquette/spi/impl/security/AuthorizationsCollectorTest.java index 3100bc3b..15b0408c 100644 --- a/broker/src/test/java/io/moquette/spi/impl/security/AuthorizationsCollectorTest.java +++ b/broker/src/test/java/io/moquette/spi/impl/security/AuthorizationsCollectorTest.java @@ -13,13 +13,12 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl.security; import org.junit.Before; import org.junit.Test; - import java.text.ParseException; - import static org.junit.Assert.*; /** @@ -28,8 +27,12 @@ import static org.junit.Assert.*; public class AuthorizationsCollectorTest { private static final Authorization RW_ANEMOMETER = new Authorization("/weather/italy/anemometer"); - private static final Authorization R_ANEMOMETER = new Authorization("/weather/italy/anemometer", Authorization.Permission.READ); - private static final Authorization W_ANEMOMETER = new Authorization("/weather/italy/anemometer", Authorization.Permission.WRITE); + private static final Authorization R_ANEMOMETER = new Authorization( + "/weather/italy/anemometer", + Authorization.Permission.READ); + private static final Authorization W_ANEMOMETER = new Authorization( + "/weather/italy/anemometer", + Authorization.Permission.WRITE); private AuthorizationsCollector authorizator; @@ -42,7 +45,7 @@ public class AuthorizationsCollectorTest { public void testParseAuthLineValid() throws ParseException { Authorization authorization = authorizator.parseAuthLine("topic /weather/italy/anemometer"); - //Verify + // Verify assertEquals(RW_ANEMOMETER, authorization); } @@ -50,7 +53,7 @@ public class AuthorizationsCollectorTest { public void testParseAuthLineValid_read() throws ParseException { Authorization authorization = authorizator.parseAuthLine("topic read /weather/italy/anemometer"); - //Verify + // Verify assertEquals(R_ANEMOMETER, authorization); } @@ -58,7 +61,7 @@ public class AuthorizationsCollectorTest { public void testParseAuthLineValid_write() throws ParseException { Authorization authorization = authorizator.parseAuthLine("topic write /weather/italy/anemometer"); - //Verify + // Verify assertEquals(W_ANEMOMETER, authorization); } @@ -66,17 +69,16 @@ public class AuthorizationsCollectorTest { public void testParseAuthLineValid_readwrite() throws ParseException { Authorization authorization = authorizator.parseAuthLine("topic readwrite /weather/italy/anemometer"); - //Verify + // Verify assertEquals(RW_ANEMOMETER, authorization); } - @Test public void testParseAuthLineValid_topic_with_space() throws ParseException { Authorization expected = new Authorization("/weather/eastern italy/anemometer"); Authorization authorization = authorizator.parseAuthLine("topic readwrite /weather/eastern italy/anemometer"); - //Verify + // Verify assertEquals(expected, authorization); } @@ -89,7 +91,7 @@ public class AuthorizationsCollectorTest { public void testCanWriteSimpleTopic() throws ParseException { authorizator.parse("topic write /sensors"); - //verify + // verify assertTrue(authorizator.canWrite("/sensors", "", "")); } @@ -97,7 +99,7 @@ public class AuthorizationsCollectorTest { public void testCanReadSimpleTopic() throws ParseException { authorizator.parse("topic read /sensors"); - //verify + // verify assertTrue(authorizator.canRead("/sensors", "", "")); } @@ -106,7 +108,7 @@ public class AuthorizationsCollectorTest { authorizator.parse("topic write /sensors"); authorizator.parse("topic read /sensors/anemometer"); - //verify + // verify assertTrue(authorizator.canWrite("/sensors", "", "")); assertFalse(authorizator.canRead("/sensors", "", "")); } @@ -115,7 +117,7 @@ public class AuthorizationsCollectorTest { public void testCanWriteMultiMatherTopic() throws ParseException { authorizator.parse("topic write /sensors/#"); - //verify + // verify assertTrue(authorizator.canWrite("/sensors/anemometer/wind", "", "")); } @@ -123,7 +125,7 @@ public class AuthorizationsCollectorTest { public void testCanWriteSingleMatherTopic() throws ParseException { authorizator.parse("topic write /sensors/+"); - //verify + // verify assertTrue(authorizator.canWrite("/sensors/anemometer", "", "")); } @@ -132,7 +134,7 @@ public class AuthorizationsCollectorTest { authorizator.parse("user john"); authorizator.parse("topic write /sensors"); - //verify + // verify assertTrue(authorizator.canWrite("/sensors", "john", "")); assertFalse(authorizator.canWrite("/sensors", "jack", "")); } @@ -141,7 +143,7 @@ public class AuthorizationsCollectorTest { public void testPatternClientLineACL() throws ParseException { authorizator.parse("pattern read /weather/italy/%c"); - //Verify + // Verify assertTrue(authorizator.canRead("/weather/italy/anemometer1", "", "anemometer1")); } @@ -149,7 +151,7 @@ public class AuthorizationsCollectorTest { public void testPatternClientAndUserLineACL() throws ParseException { authorizator.parse("pattern read /weather/%u/%c"); - //Verify + // Verify assertTrue(authorizator.canRead("/weather/italy/anemometer1", "italy", "anemometer1")); } -} \ No newline at end of file +} diff --git a/broker/src/test/java/io/moquette/spi/impl/security/DBAuthenticatorTest.java b/broker/src/test/java/io/moquette/spi/impl/security/DBAuthenticatorTest.java index 885825d2..35767684 100644 --- a/broker/src/test/java/io/moquette/spi/impl/security/DBAuthenticatorTest.java +++ b/broker/src/test/java/io/moquette/spi/impl/security/DBAuthenticatorTest.java @@ -1,15 +1,14 @@ + package io.moquette.spi.impl.security; import org.apache.commons.codec.binary.Hex; import org.junit.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.sql.*; - import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -25,7 +24,6 @@ public class DBAuthenticatorTest { public static final String SHA_256 = "SHA-256"; private Connection connection; - @Before public void setup() throws ClassNotFoundException, SQLException, NoSuchAlgorithmException { Class.forName(ORG_H2_DRIVER); @@ -33,52 +31,62 @@ public class DBAuthenticatorTest { Statement statement = this.connection.createStatement(); try { statement.execute("DROP TABLE ACCOUNT"); - } catch(SQLException sqle) { - LOG.info("Table not found, not dropping",sqle); + } catch (SQLException sqle) { + LOG.info("Table not found, not dropping", sqle); } MessageDigest digest = MessageDigest.getInstance(SHA_256); String hash = new String(Hex.encodeHex(digest.digest("password".getBytes(StandardCharsets.UTF_8)))); try { - if (statement.execute("CREATE TABLE ACCOUNT ( LOGIN VARCHAR(64), PASSWORD VARCHAR(256))")){ + if (statement.execute("CREATE TABLE ACCOUNT ( LOGIN VARCHAR(64), PASSWORD VARCHAR(256))")) { throw new SQLException("can't create USER table"); } - if (statement.execute("INSERT INTO ACCOUNT ( LOGIN , PASSWORD ) VALUES ('dbuser', '"+hash+"')")){ + if (statement.execute("INSERT INTO ACCOUNT ( LOGIN , PASSWORD ) VALUES ('dbuser', '" + hash + "')")) { throw new SQLException("can't insert in USER table"); } - } catch(SQLException sqle) { - LOG.error("Table not created, not inserted",sqle); + } catch (SQLException sqle) { + LOG.error("Table not created, not inserted", sqle); return; } LOG.info("Table User created"); statement.close(); - } @Test public void Db_verifyValid() { - final DBAuthenticator dbAuthenticator = new DBAuthenticator(ORG_H2_DRIVER, JDBC_H2_MEM_TEST, "SELECT PASSWORD FROM ACCOUNT WHERE LOGIN=?", SHA_256); - assertTrue(dbAuthenticator.checkValid(null, "dbuser","password".getBytes())); + final DBAuthenticator dbAuthenticator = new DBAuthenticator( + ORG_H2_DRIVER, + JDBC_H2_MEM_TEST, + "SELECT PASSWORD FROM ACCOUNT WHERE LOGIN=?", + SHA_256); + assertTrue(dbAuthenticator.checkValid(null, "dbuser", "password".getBytes())); } @Test - public void Db_verifyInvalidLogin(){ - final DBAuthenticator dbAuthenticator = new DBAuthenticator(ORG_H2_DRIVER, JDBC_H2_MEM_TEST, "SELECT PASSWORD FROM ACCOUNT WHERE LOGIN=?", SHA_256); - assertFalse(dbAuthenticator.checkValid(null, "dbuser2","password".getBytes())); + public void Db_verifyInvalidLogin() { + final DBAuthenticator dbAuthenticator = new DBAuthenticator( + ORG_H2_DRIVER, + JDBC_H2_MEM_TEST, + "SELECT PASSWORD FROM ACCOUNT WHERE LOGIN=?", + SHA_256); + assertFalse(dbAuthenticator.checkValid(null, "dbuser2", "password".getBytes())); } @Test - public void Db_verifyInvalidPassword(){ - final DBAuthenticator dbAuthenticator = new DBAuthenticator(ORG_H2_DRIVER, JDBC_H2_MEM_TEST, "SELECT PASSWORD FROM ACCOUNT WHERE LOGIN=?", SHA_256); - assertFalse(dbAuthenticator.checkValid(null, "dbuser","wrongPassword".getBytes())); + public void Db_verifyInvalidPassword() { + final DBAuthenticator dbAuthenticator = new DBAuthenticator( + ORG_H2_DRIVER, + JDBC_H2_MEM_TEST, + "SELECT PASSWORD FROM ACCOUNT WHERE LOGIN=?", + SHA_256); + assertFalse(dbAuthenticator.checkValid(null, "dbuser", "wrongPassword".getBytes())); } - @After - public void teardown(){ + public void teardown() { try { this.connection.close(); } catch (SQLException e) { - LOG.error("can't close connection",e); + LOG.error("can't close connection", e); } } } diff --git a/broker/src/test/java/io/moquette/spi/impl/security/FileAuthenticatorTest.java b/broker/src/test/java/io/moquette/spi/impl/security/FileAuthenticatorTest.java index 943faa66..c539ff10 100644 --- a/broker/src/test/java/io/moquette/spi/impl/security/FileAuthenticatorTest.java +++ b/broker/src/test/java/io/moquette/spi/impl/security/FileAuthenticatorTest.java @@ -13,11 +13,11 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl.security; import io.moquette.spi.security.IAuthenticator; import org.junit.Test; - import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -26,28 +26,28 @@ import static org.junit.Assert.assertTrue; * @author andrea */ public class FileAuthenticatorTest { - + @Test public void loadPasswordFile_verifyValid() { - String file = getClass().getResource("/password_file.conf").getPath(); + String file = getClass().getResource("/password_file.conf").getPath(); IAuthenticator auth = new FileAuthenticator(null, file); - + assertTrue(auth.checkValid(null, "testuser", "passwd".getBytes())); } - + @Test public void loadPasswordFile_verifyInvalid() { - String file = getClass().getResource("/password_file.conf").getPath(); + String file = getClass().getResource("/password_file.conf").getPath(); IAuthenticator auth = new FileAuthenticator(null, file); - - assertFalse(auth.checkValid(null, "testuser2", "passwd".getBytes())); - } - - @Test - public void loadPasswordFile_verifyDirectoryRef() { - IAuthenticator auth = new FileAuthenticator("", ""); - + assertFalse(auth.checkValid(null, "testuser2", "passwd".getBytes())); } -} \ No newline at end of file + @Test + public void loadPasswordFile_verifyDirectoryRef() { + IAuthenticator auth = new FileAuthenticator("", ""); + + assertFalse(auth.checkValid(null, "testuser2", "passwd".getBytes())); + } + +} diff --git a/broker/src/test/java/io/moquette/spi/impl/subscriptions/SubscriptionsStoreTest.java b/broker/src/test/java/io/moquette/spi/impl/subscriptions/SubscriptionsStoreTest.java index 6e689709..52ab5259 100644 --- a/broker/src/test/java/io/moquette/spi/impl/subscriptions/SubscriptionsStoreTest.java +++ b/broker/src/test/java/io/moquette/spi/impl/subscriptions/SubscriptionsStoreTest.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.impl.subscriptions; import io.moquette.spi.ClientSession; @@ -22,11 +23,9 @@ import io.moquette.spi.impl.MemoryStorageService; import io.netty.handler.codec.mqtt.MqttQoS; import org.junit.Before; import org.junit.Test; - import java.io.IOException; import java.text.ParseException; import java.util.List; - import static org.assertj.core.api.Assertions.*; /** @@ -141,19 +140,18 @@ public class SubscriptionsStoreTest { store.add(anySub.asClientTopicCouple()); store.add(financeAnySub.asClientTopicCouple()); - //Verify + // Verify assertThat(store.matches("finance/stock")).containsExactlyInAnyOrder(financeAnySub, anySub); assertThat(store.matches("finance/stock/ibm")).containsExactlyInAnyOrder(financeAnySub, anySub); } - @Test public void testMatchingDeepMulti_two_layer() { Subscription financeAnySub = new Subscription("FAKE_CLI_ID_1", "finance/stock/#", MqttQoS.AT_MOST_ONCE); sessionsStore.addNewSubscription(financeAnySub); store.add(financeAnySub.asClientTopicCouple()); - //Verify + // Verify assertThat(store.matches("finance/stock/ibm")).containsExactly(financeAnySub); } @@ -176,11 +174,10 @@ public class SubscriptionsStoreTest { sessionsStore.addNewSubscription(manySub); store.add(manySub.asClientTopicCouple()); - //verify + // verify assertThat(store.matches("/finance")).contains(manySub); } - @Test public void testMatchSlashSingle() { Subscription slashPlusSub = new Subscription("FAKE_CLI_ID_1", "/+", MqttQoS.AT_MOST_ONCE); @@ -190,12 +187,11 @@ public class SubscriptionsStoreTest { sessionsStore.addNewSubscription(anySub); store.add(anySub.asClientTopicCouple()); - //Verify + // Verify assertThat(store.matches("/finance")).containsOnly(slashPlusSub); assertThat(store.matches("/finance")).doesNotContain(anySub); } - @Test public void testMatchManyDeepSingle() { Subscription slashPlusSub = new Subscription("FAKE_CLI_ID_1", "/finance/+/ibm", MqttQoS.AT_MOST_ONCE); @@ -206,7 +202,7 @@ public class SubscriptionsStoreTest { sessionsStore.addNewSubscription(slashPlusDeepSub); store.add(slashPlusDeepSub.asClientTopicCouple()); - //Verify + // Verify assertThat(store.matches("/finance/stock/ibm")).containsExactlyInAnyOrder(slashPlusSub, slashPlusDeepSub); } @@ -221,7 +217,7 @@ public class SubscriptionsStoreTest { @Test public void testMatchSimpleMulti_zeroLevel() { - //check MULTI in case of zero level match + // check MULTI in case of zero level match Subscription sub = new Subscription("FAKE_CLI_ID_1", "finance/#", MqttQoS.AT_MOST_ONCE); sessionsStore.addNewSubscription(sub); store.add(sub.asClientTopicCouple()); @@ -275,7 +271,6 @@ public class SubscriptionsStoreTest { assertThat(store.matches(topic)).isEmpty(); } - @Test public void testRemoveClientSubscriptions_existingClientID() { String cliendID = "FAKE_CLID_1"; @@ -283,10 +278,10 @@ public class SubscriptionsStoreTest { sessionsStore.addNewSubscription(sub); store.add(sub.asClientTopicCouple()); - //Exercise + // Exercise store.removeForClient(cliendID); - //Verify + // Verify assertThat(store.size()).isZero(); } @@ -297,10 +292,10 @@ public class SubscriptionsStoreTest { sessionsStore.addNewSubscription(s); store.add(s.asClientTopicCouple()); - //Exercise + // Exercise store.removeForClient("FAKE_CLID_2"); - //Verify + // Verify assertThat(store.size()).isEqualTo(1); } @@ -313,7 +308,7 @@ public class SubscriptionsStoreTest { sessionsStore.addNewSubscription(specificSub); store.add(specificSub.asClientTopicCouple()); - //Verify + // Verify assertThat(store.matches("a/b").size()).isEqualTo(1); } @@ -331,7 +326,6 @@ public class SubscriptionsStoreTest { assertThat(SubscriptionsStore.matchTopics("finance/stock/ibm", "finance/#")).isTrue(); } - @Test public void testMatchTopics_single() { assertThat(SubscriptionsStore.matchTopics("finance", "+")).isTrue(); @@ -376,28 +370,28 @@ public class SubscriptionsStoreTest { memStore.initStore(); ISessionsStore sessionsStore = memStore.sessionsStore(); aStore.init(sessionsStore); - //subscribe a not active clientID1 to /topic + // subscribe a not active clientID1 to /topic sessionsStore.createNewSession("FAKE_CLI_ID_1", true); Subscription slashSub = new Subscription("FAKE_CLI_ID_1", "/topic", MqttQoS.AT_MOST_ONCE); sessionsStore.addNewSubscription(slashSub); aStore.add(slashSub.asClientTopicCouple()); - //subscribe an active clientID2 to /topic + // subscribe an active clientID2 to /topic Subscription slashSub2 = new Subscription("FAKE_CLI_ID_2", "/topic", MqttQoS.AT_MOST_ONCE); sessionsStore.addNewSubscription(slashSub2); aStore.add(new ClientTopicCouple("FAKE_CLI_ID_2", "/topic")); - //Exercise + // Exercise aStore.removeSubscription("/topic", slashSub2.getClientId()); - //Verify + // Verify Subscription remainedSubscription = aStore.matches("/topic").get(0); assertThat(remainedSubscription.getClientId()).isEqualTo(slashSub.getClientId()); } /* - Test for Issue #49 - * */ + * Test for Issue #49 + */ @Test public void duplicatedSubscriptionsWithDifferentQos() { ClientSession session2 = sessionsStore.createNewSession("client2", true); @@ -415,7 +409,7 @@ public class SubscriptionsStoreTest { System.out.println(store.dumpTree()); - //Verify + // Verify List subscriptions = store.matches("client/test/b"); assertThat(subscriptions).contains(client1SubQoS2); assertThat(subscriptions).contains(client2Sub); @@ -423,7 +417,7 @@ public class SubscriptionsStoreTest { Subscription client1Sub = subscriptions.get(subscriptions.indexOf(client1SubQoS0)); assertThat(client1SubQoS0.getRequestedQos()).isNotEqualTo(client1Sub.getRequestedQos()); - //client1SubQoS2 should override client1SubQoS0 + // client1SubQoS2 should override client1SubQoS0 assertThat(client1Sub.getRequestedQos()).isEqualTo(client1SubQoS2.getRequestedQos()); } @@ -432,7 +426,7 @@ public class SubscriptionsStoreTest { TreeNode oldRoot = new TreeNode(); final SubscriptionsStore.NodeCouple resp = store.recreatePath("/finance", oldRoot); - //Verify + // Verify assertThat(resp.root).isNotNull(); assertThat(resp.root.m_token).isNull(); assertThat(resp.root.m_children).hasSize(1); @@ -445,7 +439,7 @@ public class SubscriptionsStoreTest { final SubscriptionsStore.NodeCouple respFinance = store.recreatePath("/finance", oldRoot); final SubscriptionsStore.NodeCouple respPlus = store.recreatePath("/+", respFinance.root); - //Verify + // Verify assertThat(respPlus.root).isNotNull(); assertThat(respPlus.root.m_token).isNull(); assertThat(respPlus.root.m_children.size()).isEqualTo(1); diff --git a/broker/src/test/java/io/moquette/spi/persistence/MapDBPersistentStoreTest.java b/broker/src/test/java/io/moquette/spi/persistence/MapDBPersistentStoreTest.java index 268b135b..9f0f4a92 100644 --- a/broker/src/test/java/io/moquette/spi/persistence/MapDBPersistentStoreTest.java +++ b/broker/src/test/java/io/moquette/spi/persistence/MapDBPersistentStoreTest.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.persistence; import io.moquette.BrokerConstants; @@ -29,11 +30,9 @@ import io.netty.handler.codec.mqtt.MqttQoS; import org.junit.After; import org.junit.Before; import org.junit.Test; - import java.util.List; import java.util.Properties; import java.util.concurrent.TimeUnit; - import static org.junit.Assert.*; /** @@ -80,7 +79,7 @@ public class MapDBPersistentStoreTest { Subscription overridingSubscription = new Subscription(session1.clientID, "/topic", MqttQoS.EXACTLY_ONCE); session1.subscribe(overridingSubscription); - //Verify + // Verify List subscriptions = m_sessionsStore.listAllSubscriptions(); assertEquals(1, subscriptions.size()); Subscription sub = m_sessionsStore.getSubscription(subscriptions.get(0)); @@ -95,27 +94,28 @@ public class MapDBPersistentStoreTest { @Test public void testNextPacketID_existingClientSession() { - //Force creation of inflight map for the CLIENT session + // Force creation of inflight map for the CLIENT session int packetId = m_sessionsStore.nextPacketID("CLIENT"); assertEquals(1, packetId); - //request a second packetID + // request a second packetID packetId = m_sessionsStore.nextPacketID("CLIENT"); assertEquals(2, packetId); } @Test public void testNextPacketID() { - //request a first ID + // request a first ID int packetId = m_sessionsStore.nextPacketID("CLIENT"); - m_sessionsStore.inFlight("CLIENT", packetId, new MessageGUID("ABCDE")); //simulate an inflight + m_sessionsStore.inFlight("CLIENT", packetId, new MessageGUID("ABCDE")); // simulate an + // inflight assertEquals(1, packetId); - //release the ID + // release the ID m_sessionsStore.inFlightAck("CLIENT", packetId); - //request a second packetID, counter restarts from 0 + // request a second packetID, counter restarts from 0 packetId = m_sessionsStore.nextPacketID("CLIENT"); assertEquals(1, packetId); } @@ -124,8 +124,9 @@ public class MapDBPersistentStoreTest { public void testCloseShutdownCommitTask() throws InterruptedException { m_storageService.close(); - //verify the executor is shutdown - assertTrue("Storage service scheduler can't be stopped in 3 seconds", + // verify the executor is shutdown + assertTrue( + "Storage service scheduler can't be stopped in 3 seconds", m_storageService.m_scheduler.awaitTermination(3, TimeUnit.SECONDS)); assertTrue(m_storageService.m_scheduler.isTerminated()); } @@ -133,17 +134,19 @@ public class MapDBPersistentStoreTest { @Test public void testDropMessagesInSessionCleanAllNotRetainedStoredMessages() { m_sessionsStore.createNewSession("TestClient", true); - IMessagesStore.StoredMessage publishToStore = new IMessagesStore.StoredMessage("Hello".getBytes(), - MqttQoS.EXACTLY_ONCE, "/topic"); + IMessagesStore.StoredMessage publishToStore = new IMessagesStore.StoredMessage( + "Hello".getBytes(), + MqttQoS.EXACTLY_ONCE, + "/topic"); publishToStore.setClientID(TEST_CLIENT); publishToStore.setMessageID(1); publishToStore.setRetained(false); MessageGUID guid = m_messagesStore.storePublishForFuture(publishToStore); - //Exercise + // Exercise m_messagesStore.dropMessagesInSession("TestClient"); - //Verify the message store for session is empty. + // Verify the message store for session is empty. IMessagesStore.StoredMessage storedPublish = m_messagesStore.getMessageByGuid(guid); assertNull("The stored message must'n be present anymore", storedPublish); } @@ -151,18 +154,20 @@ public class MapDBPersistentStoreTest { @Test public void testDropMessagesInSessionDoesntCleanAnyRetainedStoredMessages() { m_sessionsStore.createNewSession("TestClient", true); - IMessagesStore.StoredMessage publishToStore = new IMessagesStore.StoredMessage("Hello".getBytes(), - MqttQoS.EXACTLY_ONCE, "/topic"); + IMessagesStore.StoredMessage publishToStore = new IMessagesStore.StoredMessage( + "Hello".getBytes(), + MqttQoS.EXACTLY_ONCE, + "/topic"); publishToStore.setClientID(TEST_CLIENT); publishToStore.setMessageID(1); publishToStore.setRetained(true); MessageGUID guid = m_messagesStore.storePublishForFuture(publishToStore); - //Exercise + // Exercise m_messagesStore.dropMessagesInSession("TestClient"); - //Verify the message store for session is empty. + // Verify the message store for session is empty. IMessagesStore.StoredMessage storedPublish = m_messagesStore.getMessageByGuid(guid); assertNotNull("The stored retained message must be present after client's session drop", storedPublish); } -} \ No newline at end of file +} diff --git a/broker/src/test/java/io/moquette/spi/persistence/MemorySessionStore.java b/broker/src/test/java/io/moquette/spi/persistence/MemorySessionStore.java index 7934f8ce..c4b803e1 100644 --- a/broker/src/test/java/io/moquette/spi/persistence/MemorySessionStore.java +++ b/broker/src/test/java/io/moquette/spi/persistence/MemorySessionStore.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.spi.persistence; import io.moquette.server.Constants; @@ -24,10 +25,8 @@ import io.moquette.spi.MessageGUID; import io.moquette.spi.impl.Utils; import io.moquette.spi.impl.subscriptions.Subscription; import io.moquette.spi.persistence.MapDBPersistentStore.PersistentSession; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.util.*; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; @@ -44,12 +43,12 @@ public class MemorySessionStore implements ISessionsStore { private Map m_persistentSessions = new HashMap<>(); - //maps clientID->[MessageId -> guid] + // maps clientID->[MessageId -> guid] private Map> m_inflightStore = new HashMap<>(); -// private Map> m_inflightIDs = new HashMap<>(); - //maps clientID->BlockingQueue + // private Map> m_inflightIDs = new HashMap<>(); + // maps clientID->BlockingQueue private Map> queues = new HashMap<>(); - //maps clientID->[MessageId -> guid] + // maps clientID->[MessageId -> guid] private Map> m_secondPhaseStore = new HashMap<>(); private Map> m_messageToGuids; @@ -183,7 +182,7 @@ public class MemorySessionStore implements ISessionsStore { /** * Return the next valid packetIdentifier for the given client session. - * */ + */ @Override public int nextPacketID(String clientID) { Map m = this.m_inflightStore.get(clientID); @@ -220,14 +219,16 @@ public class MemorySessionStore implements ISessionsStore { MessageGUID guid = m.remove(messageID); LOG.info("Moving to second phase store"); - Map messageIDs = Utils.defaultGet(m_secondPhaseStore, clientID, new HashMap()); + Map messageIDs = Utils + .defaultGet(m_secondPhaseStore, clientID, new HashMap()); messageIDs.put(messageID, guid); m_secondPhaseStore.put(clientID, messageIDs); } @Override public MessageGUID secondPhaseAcknowledged(String clientID, int messageID) { - Map messageIDs = Utils.defaultGet(m_secondPhaseStore, clientID, new HashMap()); + Map messageIDs = Utils + .defaultGet(m_secondPhaseStore, clientID, new HashMap()); MessageGUID guid = messageIDs.remove(messageID); m_secondPhaseStore.put(clientID, messageIDs); return guid; @@ -235,15 +236,15 @@ public class MemorySessionStore implements ISessionsStore { @Override public MessageGUID mapToGuid(String clientID, int messageID) { - HashMap guids = (HashMap) Utils.defaultGet(m_messageToGuids, - clientID, new HashMap()); + HashMap guids = (HashMap) Utils + .defaultGet(m_messageToGuids, clientID, new HashMap()); return guids.get(messageID); } - @Override - public StoredMessage getInflightMessage( String clientID, int messageID ) { - return null; - } + @Override + public StoredMessage getInflightMessage(String clientID, int messageID) { + return null; + } @Override public int getInflightMessagesNo(String clientID) { diff --git a/broker/src/test/java/io/moquette/testclient/Client.java b/broker/src/test/java/io/moquette/testclient/Client.java index 3a4e5a0f..f8543cb0 100644 --- a/broker/src/test/java/io/moquette/testclient/Client.java +++ b/broker/src/test/java/io/moquette/testclient/Client.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.testclient; import io.moquette.BrokerConstants; @@ -25,22 +26,22 @@ import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.mqtt.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** - * Class used just to send and receive MQTT messages without any protocol login - * in action, just use the encoder/decoder part. - * + * Class used just to send and receive MQTT messages without any protocol login in action, just use + * the encoder/decoder part. + * * @author andrea */ public class Client { - + public interface ICallback { + void call(MqttMessage msg); } - + private static final Logger LOG = LoggerFactory.getLogger(Client.class); final ClientNettyMQTTHandler handler = new ClientNettyMQTTHandler(); EventLoopGroup workerGroup; @@ -49,11 +50,11 @@ public class Client { private ICallback callback; private String clientId; private MqttMessage receivedMsg; - + public Client(String host) { this(host, BrokerConstants.PORT); } - + public Client(String host, int port) { handler.setClient(this); workerGroup = new NioEventLoopGroup(); @@ -63,6 +64,7 @@ public class Client { b.channel(NioSocketChannel.class); b.option(ChannelOption.SO_KEEPALIVE, true); b.handler(new ChannelInitializer() { + @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); @@ -71,10 +73,10 @@ public class Client { pipeline.addLast("handler", handler); } }); - + // Start the client. m_channel = b.connect(host, port).sync().channel(); - } catch (Exception ex) { + } catch (Exception ex) { LOG.error("Error received in client setup", ex); workerGroup.shutdownGracefully(); } @@ -86,44 +88,49 @@ public class Client { } public void connect(String willTestamentTopic, String willTestamentMsg) { - MqttFixedHeader mqttFixedHeader = new MqttFixedHeader(MqttMessageType.CONNECT, false, MqttQoS.AT_MOST_ONCE, false, 0); - MqttConnectVariableHeader mqttConnectVariableHeader = - new MqttConnectVariableHeader( - MqttVersion.MQTT_3_1.protocolName(), - MqttVersion.MQTT_3_1.protocolLevel(), - false, - false, - false, - MqttQoS.AT_MOST_ONCE.value(), - true, - true, - 2); - MqttConnectPayload mqttConnectPayload = new MqttConnectPayload(this.clientId, willTestamentTopic, willTestamentMsg, - null, null); - MqttConnectMessage connectMessage = new MqttConnectMessage(mqttFixedHeader, mqttConnectVariableHeader, + MqttFixedHeader mqttFixedHeader = new MqttFixedHeader( + MqttMessageType.CONNECT, + false, + MqttQoS.AT_MOST_ONCE, + false, + 0); + MqttConnectVariableHeader mqttConnectVariableHeader = new MqttConnectVariableHeader( + MqttVersion.MQTT_3_1.protocolName(), + MqttVersion.MQTT_3_1.protocolLevel(), + false, + false, + false, + MqttQoS.AT_MOST_ONCE.value(), + true, + true, + 2); + MqttConnectPayload mqttConnectPayload = new MqttConnectPayload( + this.clientId, + willTestamentTopic, + willTestamentMsg, + null, + null); + MqttConnectMessage connectMessage = new MqttConnectMessage( + mqttFixedHeader, + mqttConnectVariableHeader, mqttConnectPayload); - - /*ConnectMessage connectMessage = new ConnectMessage(); - connectMessage.setProtocolVersion((byte) 3); - connectMessage.setClientID(this.clientId); - connectMessage.setKeepAlive(2); //secs - connectMessage.setWillFlag(true); - connectMessage.setWillMessage(willTestamentMsg.getBytes()); - connectMessage.setWillTopic(willTestamentTopic); - connectMessage.setWillQos(MqttQoS.AT_MOST_ONCE.byteValue());*/ + /* + * ConnectMessage connectMessage = new ConnectMessage(); + * connectMessage.setProtocolVersion((byte) 3); connectMessage.setClientID(this.clientId); + * connectMessage.setKeepAlive(2); //secs connectMessage.setWillFlag(true); + * connectMessage.setWillMessage(willTestamentMsg.getBytes()); + * connectMessage.setWillTopic(willTestamentTopic); + * connectMessage.setWillQos(MqttQoS.AT_MOST_ONCE.byteValue()); + */ doConnect(connectMessage); } public void connect() { - MqttConnectMessage connectMessage = MessageBuilder.connect() - .protocolVersion(MqttVersion.MQTT_3_1_1) - .clientId("") - .keepAlive(2) //secs - .willFlag(false) - .willQoS(MqttQoS.AT_MOST_ONCE) - .build(); + MqttConnectMessage connectMessage = MessageBuilder.connect().protocolVersion(MqttVersion.MQTT_3_1_1) + .clientId("").keepAlive(2) // secs + .willFlag(false).willQoS(MqttQoS.AT_MOST_ONCE).build(); doConnect(connectMessage); } @@ -154,7 +161,7 @@ public class Client { public void setCallback(ICallback callback) { this.callback = callback; } - + public void sendMessage(MqttMessage msg) { m_channel.writeAndFlush(msg); } @@ -169,11 +176,11 @@ public class Client { this.callback.call(msg); } } - + void setConnectionLost(boolean status) { m_connectionLost = status; } - + public boolean isConnectionLost() { return m_connectionLost; } diff --git a/broker/src/test/java/io/moquette/testclient/ClientNettyMQTTHandler.java b/broker/src/test/java/io/moquette/testclient/ClientNettyMQTTHandler.java index a7c8aeda..94073898 100644 --- a/broker/src/test/java/io/moquette/testclient/ClientNettyMQTTHandler.java +++ b/broker/src/test/java/io/moquette/testclient/ClientNettyMQTTHandler.java @@ -13,6 +13,7 @@ * * You may elect to redistribute this code under either of these licenses. */ + package io.moquette.testclient; import io.moquette.server.netty.NettyMQTTHandler; @@ -29,25 +30,25 @@ import org.slf4j.LoggerFactory; */ @ChannelHandler.Sharable class ClientNettyMQTTHandler extends ChannelInboundHandlerAdapter { - + private static final Logger LOG = LoggerFactory.getLogger(NettyMQTTHandler.class); private Client m_client; - + @Override public void channelRead(ChannelHandlerContext ctx, Object message) { MqttMessage msg = (MqttMessage) message; LOG.info("Received a message of type {}", msg.fixedHeader().messageType()); m_client.messageReceived(msg); } - + @Override - public void channelInactive(ChannelHandlerContext ctx)throws Exception { + public void channelInactive(ChannelHandlerContext ctx) throws Exception { m_client.setConnectionLost(true); - ctx.close(/*false*/); + ctx.close(/* false */); } void setClient(Client client) { m_client = client; } - + } diff --git a/broker/src/test/java/io/moquette/testclient/RawClient.java b/broker/src/test/java/io/moquette/testclient/RawClient.java index 71b67533..96a54ce3 100644 --- a/broker/src/test/java/io/moquette/testclient/RawClient.java +++ b/broker/src/test/java/io/moquette/testclient/RawClient.java @@ -1,3 +1,4 @@ + package io.moquette.testclient; import io.netty.bootstrap.Bootstrap; @@ -11,15 +12,14 @@ import io.netty.util.ReferenceCountUtil; import io.moquette.Utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.io.UnsupportedEncodingException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; /** - * This class is used to have a fluent interface to interact with a server. - * Inspired by org.kaazing.robot + * This class is used to have a fluent interface to interact with a server. Inspired by + * org.kaazing.robot */ public class RawClient { @@ -41,9 +41,9 @@ public class RawClient { @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { - //m_client.setConnectionLost(true); + // m_client.setConnectionLost(true); disconnectLatch.countDown(); - ctx.close(/*false*/); + ctx.close(/* false */); } } @@ -71,6 +71,7 @@ public class RawClient { b.channel(NioSocketChannel.class); b.option(ChannelOption.SO_KEEPALIVE, true); b.handler(new ChannelInitializer() { + @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); @@ -117,14 +118,14 @@ public class RawClient { /** * Write just String bytes not length - * */ + */ public RawClient write(String str) { ByteBuf out = Unpooled.buffer(str.length()); byte[] raw; try { raw = str.getBytes("UTF-8"); - //NB every Java platform has got UTF-8 encoding by default, so this - //exception are never raised. + // NB every Java platform has got UTF-8 encoding by default, so this + // exception are never raised. } catch (UnsupportedEncodingException ex) { throw new IllegalStateException(ex); } @@ -153,14 +154,14 @@ public class RawClient { /** * Expect the closing of the underling channel, with timeout - * */ + */ public void closed(long timeout) throws InterruptedException { disconnectLatch.await(timeout, TimeUnit.MILLISECONDS); } /** * Expect closing the connect with unbound time - * */ + */ public void closed() throws InterruptedException { disconnectLatch.await(); } diff --git a/checkstyle-suppressions.xml b/checkstyle-suppressions.xml new file mode 100644 index 00000000..b5ac72e0 --- /dev/null +++ b/checkstyle-suppressions.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/checkstyle.xml b/checkstyle.xml index bf13ff3f..2f2c7a34 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -22,7 +22,7 @@ @@ -118,9 +120,11 @@ +