Added username to all messages. From a consumer perspective the username is more useful than a clientID which is often autogenerated.
This commit is contained in:
@@ -37,13 +37,13 @@ public interface Interceptor {
|
|||||||
|
|
||||||
void notifyClientConnected(ConnectMessage msg);
|
void notifyClientConnected(ConnectMessage msg);
|
||||||
|
|
||||||
void notifyClientDisconnected(String clientID);
|
void notifyClientDisconnected(String clientID, String username);
|
||||||
|
|
||||||
void notifyTopicPublished(PublishMessage msg, String clientID);
|
void notifyTopicPublished(PublishMessage msg, String clientID, final String username);
|
||||||
|
|
||||||
void notifyTopicSubscribed(Subscription sub);
|
void notifyTopicSubscribed(Subscription sub, final String username);
|
||||||
|
|
||||||
void notifyTopicUnsubscribed(String topic, String clientID);
|
void notifyTopicUnsubscribed(String topic, String clientID, final String username);
|
||||||
|
|
||||||
void notifyMessageConsumed(InterceptConsumedMessage msg);
|
void notifyMessageConsumed(InterceptConsumedMessage msg);
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-1
@@ -4,12 +4,18 @@ import static io.moquette.spi.IMessagesStore.StoredMessage;
|
|||||||
|
|
||||||
public class InterceptConsumedMessage {
|
public class InterceptConsumedMessage {
|
||||||
final private StoredMessage msg;
|
final private StoredMessage msg;
|
||||||
|
private final String username;
|
||||||
|
|
||||||
public InterceptConsumedMessage( final StoredMessage msg) {
|
public InterceptConsumedMessage( final StoredMessage msg, String username) {
|
||||||
this.msg = msg;
|
this.msg = msg;
|
||||||
|
this.username = username;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StoredMessage getMsg() {
|
public StoredMessage getMsg() {
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-1
@@ -5,12 +5,18 @@ package io.moquette.interception.messages;
|
|||||||
*/
|
*/
|
||||||
public class InterceptDisconnectMessage {
|
public class InterceptDisconnectMessage {
|
||||||
private final String clientID;
|
private final String clientID;
|
||||||
|
private final String username;
|
||||||
|
|
||||||
public InterceptDisconnectMessage(String clientID) {
|
public InterceptDisconnectMessage(String clientID, String username) {
|
||||||
this.clientID = clientID;
|
this.clientID = clientID;
|
||||||
|
this.username = username;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getClientID() {
|
public String getClientID() {
|
||||||
return clientID;
|
return clientID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,13 @@ import java.nio.ByteBuffer;
|
|||||||
public class InterceptPublishMessage extends InterceptAbstractMessage {
|
public class InterceptPublishMessage extends InterceptAbstractMessage {
|
||||||
private final PublishMessage msg;
|
private final PublishMessage msg;
|
||||||
private final String clientID;
|
private final String clientID;
|
||||||
|
private final String username;
|
||||||
|
|
||||||
public InterceptPublishMessage(PublishMessage msg, String clientID) {
|
public InterceptPublishMessage(PublishMessage msg, String clientID, String username) {
|
||||||
super(msg);
|
super(msg);
|
||||||
this.msg = msg;
|
this.msg = msg;
|
||||||
this.clientID = clientID;
|
this.clientID = clientID;
|
||||||
|
this.username = username;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTopicName() {
|
public String getTopicName() {
|
||||||
@@ -28,4 +30,8 @@ public class InterceptPublishMessage extends InterceptAbstractMessage {
|
|||||||
public String getClientID() {
|
public String getClientID() {
|
||||||
return clientID;
|
return clientID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-1
@@ -8,9 +8,11 @@ import io.moquette.spi.impl.subscriptions.Subscription;
|
|||||||
*/
|
*/
|
||||||
public class InterceptSubscribeMessage {
|
public class InterceptSubscribeMessage {
|
||||||
private final Subscription subscription;
|
private final Subscription subscription;
|
||||||
|
private final String username;
|
||||||
|
|
||||||
public InterceptSubscribeMessage(Subscription subscription) {
|
public InterceptSubscribeMessage(Subscription subscription, String username) {
|
||||||
this.subscription = subscription;
|
this.subscription = subscription;
|
||||||
|
this.username = username;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getClientID() {
|
public String getClientID() {
|
||||||
@@ -24,4 +26,8 @@ public class InterceptSubscribeMessage {
|
|||||||
public String getTopicFilter() {
|
public String getTopicFilter() {
|
||||||
return subscription.getTopicFilter();
|
return subscription.getTopicFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-1
@@ -6,10 +6,12 @@ package io.moquette.interception.messages;
|
|||||||
public class InterceptUnsubscribeMessage {
|
public class InterceptUnsubscribeMessage {
|
||||||
private final String topicFilter;
|
private final String topicFilter;
|
||||||
private final String clientID;
|
private final String clientID;
|
||||||
|
private final String username;
|
||||||
|
|
||||||
public InterceptUnsubscribeMessage(String topicFilter, String clientID) {
|
public InterceptUnsubscribeMessage(String topicFilter, String clientID, String username) {
|
||||||
this.topicFilter = topicFilter;
|
this.topicFilter = topicFilter;
|
||||||
this.clientID = clientID;
|
this.clientID = clientID;
|
||||||
|
this.username = username;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTopicFilter() {
|
public String getTopicFilter() {
|
||||||
@@ -19,4 +21,8 @@ public class InterceptUnsubscribeMessage {
|
|||||||
public String getClientID() {
|
public String getClientID() {
|
||||||
return clientID;
|
return clientID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,48 +60,48 @@ final class BrokerInterceptor implements Interceptor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notifyClientDisconnected(final String clientID) {
|
public void notifyClientDisconnected(final String clientID, final String username ) {
|
||||||
for (final InterceptHandler handler : this.handlers) {
|
for (final InterceptHandler handler : this.handlers) {
|
||||||
executor.execute(new Runnable() {
|
executor.execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
handler.onDisconnect(new InterceptDisconnectMessage(clientID));
|
handler.onDisconnect(new InterceptDisconnectMessage(clientID, username));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notifyTopicPublished(final PublishMessage msg, final String clientID) {
|
public void notifyTopicPublished(final PublishMessage msg, final String clientID, final String username) {
|
||||||
for (final InterceptHandler handler : this.handlers) {
|
for (final InterceptHandler handler : this.handlers) {
|
||||||
executor.execute(new Runnable() {
|
executor.execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
handler.onPublish(new InterceptPublishMessage(msg, clientID));
|
handler.onPublish(new InterceptPublishMessage(msg, clientID, username));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notifyTopicSubscribed(final Subscription sub) {
|
public void notifyTopicSubscribed(final Subscription sub, final String username) {
|
||||||
for (final InterceptHandler handler : this.handlers) {
|
for (final InterceptHandler handler : this.handlers) {
|
||||||
executor.execute(new Runnable() {
|
executor.execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
handler.onSubscribe(new InterceptSubscribeMessage(sub));
|
handler.onSubscribe(new InterceptSubscribeMessage(sub, username));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notifyTopicUnsubscribed(final String topic, final String clientID) {
|
public void notifyTopicUnsubscribed(final String topic, final String clientID, final String username) {
|
||||||
for (final InterceptHandler handler : this.handlers) {
|
for (final InterceptHandler handler : this.handlers) {
|
||||||
executor.execute(new Runnable() {
|
executor.execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
handler.onUnsubscribe(new InterceptUnsubscribeMessage(topic, clientID));
|
handler.onUnsubscribe(new InterceptUnsubscribeMessage(topic, clientID, username));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,14 +19,13 @@ import java.nio.ByteBuffer;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import io.moquette.server.ConnectionDescriptor;
|
import io.moquette.server.ConnectionDescriptor;
|
||||||
import io.moquette.server.netty.AutoFlushHandler;
|
|
||||||
import io.moquette.server.netty.NettyUtils;
|
import io.moquette.server.netty.NettyUtils;
|
||||||
import io.moquette.spi.ClientSession;
|
import io.moquette.spi.ClientSession;
|
||||||
import io.moquette.spi.IMatchingCondition;
|
import io.moquette.spi.IMatchingCondition;
|
||||||
import io.moquette.spi.IMessagesStore;
|
import io.moquette.spi.IMessagesStore;
|
||||||
|
import io.moquette.spi.IMessagesStore.StoredMessage;
|
||||||
import io.moquette.spi.ISessionsStore;
|
import io.moquette.spi.ISessionsStore;
|
||||||
import io.moquette.spi.security.IAuthenticator;
|
import io.moquette.spi.security.IAuthenticator;
|
||||||
import io.moquette.spi.security.IAuthorizator;
|
import io.moquette.spi.security.IAuthorizator;
|
||||||
@@ -35,6 +34,7 @@ import io.moquette.spi.impl.subscriptions.Subscription;
|
|||||||
|
|
||||||
import static io.moquette.parser.netty.Utils.VERSION_3_1;
|
import static io.moquette.parser.netty.Utils.VERSION_3_1;
|
||||||
import static io.moquette.parser.netty.Utils.VERSION_3_1_1;
|
import static io.moquette.parser.netty.Utils.VERSION_3_1_1;
|
||||||
|
import io.moquette.interception.messages.InterceptConsumedMessage;
|
||||||
import io.moquette.parser.proto.messages.AbstractMessage;
|
import io.moquette.parser.proto.messages.AbstractMessage;
|
||||||
import io.moquette.parser.proto.messages.AbstractMessage.QOSType;
|
import io.moquette.parser.proto.messages.AbstractMessage.QOSType;
|
||||||
import io.moquette.parser.proto.messages.ConnAckMessage;
|
import io.moquette.parser.proto.messages.ConnAckMessage;
|
||||||
@@ -209,9 +209,8 @@ public class ProtocolProcessor {
|
|||||||
byte[] willPayload = msg.getWillMessage();
|
byte[] willPayload = msg.getWillMessage();
|
||||||
ByteBuffer bb = (ByteBuffer) ByteBuffer.allocate(willPayload.length).put(willPayload).flip();
|
ByteBuffer bb = (ByteBuffer) ByteBuffer.allocate(willPayload.length).put(willPayload).flip();
|
||||||
//save the will testament in the clientID store
|
//save the will testament in the clientID store
|
||||||
WillMessage will = new WillMessage(msg.getWillTopic(), bb, msg.isWillRetain(),willQos);
|
WillMessage will = new WillMessage(msg.getWillTopic(), bb, msg.isWillRetain(),willQos );
|
||||||
m_willStore.put(msg.getClientID(), will);
|
m_willStore.put(msg.getClientID(), will);
|
||||||
LOG.info("Session for clientID <{}> with will to topic {}", msg.getClientID(), msg.getWillTopic());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnAckMessage okResp = new ConnAckMessage();
|
ConnAckMessage okResp = new ConnAckMessage();
|
||||||
@@ -241,19 +240,8 @@ public class ProtocolProcessor {
|
|||||||
//force the republish of stored QoS1 and QoS2
|
//force the republish of stored QoS1 and QoS2
|
||||||
republishStoredInSession(clientSession);
|
republishStoredInSession(clientSession);
|
||||||
}
|
}
|
||||||
int flushIntervalMs = 500/*(keepAlive * 1000) / 2*/;
|
|
||||||
setupAutoFlusher(channel.pipeline(), flushIntervalMs);
|
|
||||||
LOG.info("CONNECT processed");
|
LOG.info("CONNECT processed");
|
||||||
}
|
// LOG.info("CONNECT clients descriptors {}", m_clientIDs);
|
||||||
|
|
||||||
private void setupAutoFlusher(ChannelPipeline pipeline, int flushIntervalMs) {
|
|
||||||
AutoFlushHandler autoFlushHandler = new AutoFlushHandler(flushIntervalMs, TimeUnit.MILLISECONDS);
|
|
||||||
try {
|
|
||||||
pipeline.addAfter("idleEventHandler", "autoFlusher", autoFlushHandler);
|
|
||||||
} catch (NoSuchElementException nseex) {
|
|
||||||
//the idleEventHandler is not present on the pipeline
|
|
||||||
pipeline.addFirst("autoFlusher", autoFlushHandler);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setIdleTime(ChannelPipeline pipeline, int idleTime) {
|
private void setIdleTime(ChannelPipeline pipeline, int idleTime) {
|
||||||
@@ -289,13 +277,18 @@ public class ProtocolProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processPubAck(Channel channel, PubAckMessage msg) {
|
public void processPubAck(Channel session, PubAckMessage msg) {
|
||||||
String clientID = NettyUtils.clientID(channel);
|
String clientID = NettyUtils.clientID(session);
|
||||||
int messageID = msg.getMessageID();
|
int messageID = msg.getMessageID();
|
||||||
|
String username = NettyUtils.userName(session);
|
||||||
|
StoredMessage inflightMsg = m_sessionsStore.getInflightMessage(clientID, messageID);
|
||||||
|
|
||||||
//Remove the message from message store
|
//Remove the message from message store
|
||||||
ClientSession targetSession = m_sessionsStore.sessionForClient(clientID);
|
ClientSession targetSession = m_sessionsStore.sessionForClient(clientID);
|
||||||
verifyToActivate(clientID, targetSession);
|
verifyToActivate(clientID, targetSession);
|
||||||
targetSession.inFlightAcknowledged(messageID);
|
targetSession.inFlightAcknowledged(messageID);
|
||||||
|
|
||||||
|
m_interceptor.notifyMessageConsumed(new InterceptConsumedMessage(inflightMsg, username));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyToActivate(String clientID, ClientSession targetSession) {
|
private void verifyToActivate(String clientID, ClientSession targetSession) {
|
||||||
@@ -317,13 +310,13 @@ public class ProtocolProcessor {
|
|||||||
return pub;
|
return pub;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processPublish(Channel channel, PublishMessage msg) {
|
public void processPublish(Channel session, PublishMessage msg) {
|
||||||
LOG.trace("PUB --PUBLISH--> SRV executePublish invoked with {}", msg);
|
LOG.trace("PUB --PUBLISH--> SRV executePublish invoked with {}", msg);
|
||||||
String clientID = NettyUtils.clientID(channel);
|
String clientID = NettyUtils.clientID(session);
|
||||||
final String topic = msg.getTopicName();
|
final String topic = msg.getTopicName();
|
||||||
//check if the topic can be wrote
|
//check if the topic can be wrote
|
||||||
String user = NettyUtils.userName(channel);
|
String username = NettyUtils.userName(session);
|
||||||
if (!m_authorizator.canWrite(topic, user, clientID)) {
|
if (!m_authorizator.canWrite(topic, username, clientID)) {
|
||||||
LOG.debug("topic {} doesn't have write credentials", topic);
|
LOG.debug("topic {} doesn't have write credentials", topic);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -363,7 +356,7 @@ public class ProtocolProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_interceptor.notifyTopicPublished(msg, clientID);
|
m_interceptor.notifyTopicPublished(msg, clientID, username);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -471,11 +464,9 @@ public class ProtocolProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void directSend(ClientSession clientsession, String topic, AbstractMessage.QOSType qos,
|
protected void directSend(ClientSession clientsession, String topic, AbstractMessage.QOSType qos, ByteBuffer message, boolean retained, Integer messageID) {
|
||||||
ByteBuffer message, boolean retained, Integer messageID) {
|
|
||||||
String clientId = clientsession.clientID;
|
String clientId = clientsession.clientID;
|
||||||
LOG.debug("directSend invoked clientId <{}> on topic <{}> QoS {} retained {} messageID {}",
|
LOG.debug("directSend invoked clientId <{}> on topic <{}> QoS {} retained {} messageID {}", clientId, topic, qos, retained, messageID);
|
||||||
clientId, topic, qos, retained, messageID);
|
|
||||||
PublishMessage pubMessage = new PublishMessage();
|
PublishMessage pubMessage = new PublishMessage();
|
||||||
pubMessage.setRetainFlag(retained);
|
pubMessage.setRetainFlag(retained);
|
||||||
pubMessage.setTopicName(topic);
|
pubMessage.setTopicName(topic);
|
||||||
@@ -491,32 +482,22 @@ public class ProtocolProcessor {
|
|||||||
pubMessage.setMessageID(messageID);
|
pubMessage.setMessageID(messageID);
|
||||||
} else {
|
} else {
|
||||||
if (messageID != null) {
|
if (messageID != null) {
|
||||||
throw new RuntimeException("Internal bad error, trying to forwardPublish a QoS 0 message " +
|
throw new RuntimeException("Internal bad error, trying to forwardPublish a QoS 0 message with PacketIdentifier: " + messageID);
|
||||||
"with PacketIdentifier: " + messageID);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_clientIDs == null) {
|
if (m_clientIDs == null) {
|
||||||
throw new RuntimeException("Internal bad error, found m_clientIDs to null while it should be " +
|
throw new RuntimeException("Internal bad error, found m_clientIDs to null while it should be initialized, somewhere it's overwritten!!");
|
||||||
"initialized, somewhere it's overwritten!!");
|
|
||||||
}
|
}
|
||||||
//LOG.trace("clientIDs are {}", m_clientIDs);
|
LOG.debug("clientIDs are {}", m_clientIDs);
|
||||||
if (m_clientIDs.get(clientId) == null) {
|
if (m_clientIDs.get(clientId) == null) {
|
||||||
//TODO while we were publishing to the target client, that client disconnected,
|
//TODO while we were publishing to the target client, that client disconnected,
|
||||||
// could happen is not an error HANDLE IT
|
// could happen is not an error HANDLE IT
|
||||||
throw new RuntimeException(String.format("Can't find a ConnectionDescriptor for client <%s> in cache <%s>",
|
throw new RuntimeException(String.format("Can't find a ConnectionDescriptor for client <%s> in cache <%s>", clientId, m_clientIDs));
|
||||||
clientId, m_clientIDs));
|
|
||||||
}
|
}
|
||||||
Channel channel = m_clientIDs.get(clientId).channel;
|
Channel channel = m_clientIDs.get(clientId).channel;
|
||||||
LOG.trace("Session for clientId {}", clientId);
|
LOG.debug("Session for clientId {} is {}", clientId, channel);
|
||||||
// channel.writeAndFlush(pubMessage);
|
channel.writeAndFlush(pubMessage);
|
||||||
if (channel.isWritable()) {
|
|
||||||
//if channel is writable don't enqueue
|
|
||||||
channel.write(pubMessage);
|
|
||||||
} else {
|
|
||||||
//enqueue to the client session
|
|
||||||
clientsession.enqueue(pubMessage);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendPubRec(String clientID, int messageID) {
|
private void sendPubRec(String clientID, int messageID) {
|
||||||
@@ -598,15 +579,18 @@ public class ProtocolProcessor {
|
|||||||
public void processPubComp(Channel channel, PubCompMessage msg) {
|
public void processPubComp(Channel channel, PubCompMessage msg) {
|
||||||
String clientID = NettyUtils.clientID(channel);
|
String clientID = NettyUtils.clientID(channel);
|
||||||
int messageID = msg.getMessageID();
|
int messageID = msg.getMessageID();
|
||||||
|
StoredMessage inflightMsg = m_sessionsStore.getInflightMessage( clientID, messageID );
|
||||||
|
|
||||||
LOG.debug("\t\tSRV <--PUBCOMP-- SUB processPubComp invoked for clientID {} ad messageID {}", clientID, messageID);
|
LOG.debug("\t\tSRV <--PUBCOMP-- SUB processPubComp invoked for clientID {} ad 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);
|
ClientSession targetSession = m_sessionsStore.sessionForClient(clientID);
|
||||||
verifyToActivate(clientID, targetSession);
|
verifyToActivate(clientID, targetSession);
|
||||||
targetSession.secondPhaseAcknowledged(messageID);
|
targetSession.secondPhaseAcknowledged(messageID);
|
||||||
|
String username = NettyUtils.userName(channel);
|
||||||
|
m_interceptor.notifyMessageConsumed( new InterceptConsumedMessage(inflightMsg, username) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processDisconnect(Channel channel) throws InterruptedException {
|
public void processDisconnect(Channel channel) {
|
||||||
channel.flush();
|
|
||||||
String clientID = NettyUtils.clientID(channel);
|
String clientID = NettyUtils.clientID(channel);
|
||||||
boolean cleanSession = NettyUtils.cleanSession(channel);
|
boolean cleanSession = NettyUtils.cleanSession(channel);
|
||||||
LOG.info("DISCONNECT client <{}> with clean session {}", clientID, cleanSession);
|
LOG.info("DISCONNECT client <{}> with clean session {}", clientID, cleanSession);
|
||||||
@@ -619,7 +603,8 @@ public class ProtocolProcessor {
|
|||||||
//cleanup the will store
|
//cleanup the will store
|
||||||
m_willStore.remove(clientID);
|
m_willStore.remove(clientID);
|
||||||
|
|
||||||
m_interceptor.notifyClientDisconnected(clientID);
|
String username = NettyUtils.userName(channel);
|
||||||
|
m_interceptor.notifyClientDisconnected(clientID, username);
|
||||||
LOG.info("DISCONNECT client <{}> finished", clientID, cleanSession);
|
LOG.info("DISCONNECT client <{}> finished", clientID, cleanSession);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -665,7 +650,8 @@ public class ProtocolProcessor {
|
|||||||
|
|
||||||
subscriptions.removeSubscription(topic, clientID);
|
subscriptions.removeSubscription(topic, clientID);
|
||||||
clientSession.unsubscribeFrom(topic);
|
clientSession.unsubscribeFrom(topic);
|
||||||
m_interceptor.notifyTopicUnsubscribed(topic, clientID);
|
String username = NettyUtils.userName(channel);
|
||||||
|
m_interceptor.notifyTopicUnsubscribed(topic, clientID, username);
|
||||||
}
|
}
|
||||||
|
|
||||||
//ack the client
|
//ack the client
|
||||||
@@ -686,10 +672,10 @@ public class ProtocolProcessor {
|
|||||||
SubAckMessage ackMessage = new SubAckMessage();
|
SubAckMessage ackMessage = new SubAckMessage();
|
||||||
ackMessage.setMessageID(msg.getMessageID());
|
ackMessage.setMessageID(msg.getMessageID());
|
||||||
|
|
||||||
String user = NettyUtils.userName(channel);
|
String username = NettyUtils.userName(channel);
|
||||||
List<Subscription> newSubscriptions = new ArrayList<>();
|
List<Subscription> newSubscriptions = new ArrayList<>();
|
||||||
for (SubscribeMessage.Couple req : msg.subscriptions()) {
|
for (SubscribeMessage.Couple req : msg.subscriptions()) {
|
||||||
if (!m_authorizator.canRead(req.topicFilter, user, clientSession.clientID)) {
|
if (!m_authorizator.canRead(req.topicFilter, username, clientSession.clientID)) {
|
||||||
//send SUBACK with 0x80, the user hasn't credentials to read the topic
|
//send SUBACK with 0x80, the user hasn't credentials to read the topic
|
||||||
LOG.debug("topic {} doesn't have read credentials", req.topicFilter);
|
LOG.debug("topic {} doesn't have read credentials", req.topicFilter);
|
||||||
ackMessage.addType( AbstractMessage.QOSType.FAILURE);
|
ackMessage.addType( AbstractMessage.QOSType.FAILURE);
|
||||||
@@ -714,17 +700,18 @@ public class ProtocolProcessor {
|
|||||||
|
|
||||||
//fire the publish
|
//fire the publish
|
||||||
for(Subscription subscription : newSubscriptions) {
|
for(Subscription subscription : newSubscriptions) {
|
||||||
subscribeSingleTopic(subscription);
|
subscribeSingleTopic(subscription, username);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean subscribeSingleTopic(final Subscription newSubscription) {
|
private boolean subscribeSingleTopic(final Subscription newSubscription, String username) {
|
||||||
subscriptions.add(newSubscription.asClientTopicCouple());
|
subscriptions.add(newSubscription.asClientTopicCouple());
|
||||||
|
|
||||||
//scans retained messages to be published to the new subscription
|
//scans retained messages to be published to the new subscription
|
||||||
//TODO this is ugly, it does a linear scan on potential big dataset
|
//TODO this is ugly, it does a linear scan on potential big dataset
|
||||||
Collection<IMessagesStore.StoredMessage> messages = m_messagesStore.searchMatching(new IMatchingCondition() {
|
Collection<IMessagesStore.StoredMessage> messages = m_messagesStore.searchMatching(new IMatchingCondition() {
|
||||||
public boolean match(String key) {
|
@Override
|
||||||
|
public boolean match(String key) {
|
||||||
return SubscriptionsStore.matchTopics(key, newSubscription.getTopicFilter());
|
return SubscriptionsStore.matchTopics(key, newSubscription.getTopicFilter());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -741,22 +728,7 @@ public class ProtocolProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//notify the Observables
|
//notify the Observables
|
||||||
m_interceptor.notifyTopicSubscribed(newSubscription);
|
m_interceptor.notifyTopicSubscribed(newSubscription, username);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifyChannelWritable(Channel channel) {
|
|
||||||
String clientID = NettyUtils.clientID(channel);
|
|
||||||
ClientSession clientSession = m_sessionsStore.sessionForClient(clientID);
|
|
||||||
boolean emptyQueue = false;
|
|
||||||
while (channel.isWritable() && !emptyQueue) {
|
|
||||||
AbstractMessage msg = clientSession.dequeue();
|
|
||||||
if (msg == null) {
|
|
||||||
emptyQueue = true;
|
|
||||||
} else {
|
|
||||||
channel.write(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
channel.flush();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,28 +97,28 @@ public class BrokerInterceptorTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNotifyClientDisconnected() throws Exception {
|
public void testNotifyClientDisconnected() throws Exception {
|
||||||
interceptor.notifyClientDisconnected("cli1234");
|
interceptor.notifyClientDisconnected("cli1234","cli1234");
|
||||||
interval();
|
interval();
|
||||||
assertEquals(50, n.get());
|
assertEquals(50, n.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNotifyTopicPublished() throws Exception {
|
public void testNotifyTopicPublished() throws Exception {
|
||||||
interceptor.notifyTopicPublished(new PublishMessage(), "cli1234");
|
interceptor.notifyTopicPublished(new PublishMessage(), "cli1234", "cli1234");
|
||||||
interval();
|
interval();
|
||||||
assertEquals(60, n.get());
|
assertEquals(60, n.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNotifyTopicSubscribed() throws Exception {
|
public void testNotifyTopicSubscribed() throws Exception {
|
||||||
interceptor.notifyTopicSubscribed(new Subscription("cli1", "o2", AbstractMessage.QOSType.MOST_ONE));
|
interceptor.notifyTopicSubscribed(new Subscription("cli1", "o2", AbstractMessage.QOSType.MOST_ONE), "cli1234");
|
||||||
interval();
|
interval();
|
||||||
assertEquals(70, n.get());
|
assertEquals(70, n.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNotifyTopicUnsubscribed() throws Exception {
|
public void testNotifyTopicUnsubscribed() throws Exception {
|
||||||
interceptor.notifyTopicUnsubscribed("o2", "cli1234");
|
interceptor.notifyTopicUnsubscribed("o2", "cli1234", "cli1234");
|
||||||
interval();
|
interval();
|
||||||
assertEquals(80, n.get());
|
assertEquals(80, n.get());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user