Refactoring, dropped unuseful ServerChannel abstraction in favor on Netty's Channel

This commit is contained in:
andsel
2016-01-24 19:21:24 +01:00
parent beb556c73c
commit 7b1db3e1db
13 changed files with 164 additions and 256 deletions
@@ -1,35 +0,0 @@
/*
* Copyright (c) 2012-2015 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.moquette.server;
import io.netty.util.AttributeKey;
/**
*
* @author andrea
*/
public interface ServerChannel {
Object getAttribute(AttributeKey<Object> key);
void setAttribute(AttributeKey<Object> key, Object value);
void setIdleTime(int idleTime);
void close(boolean immediately);
void write(Object value);
}
@@ -20,13 +20,12 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.timeout.IdleStateHandler; import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.Attribute; import io.netty.util.Attribute;
import io.netty.util.AttributeKey; import io.netty.util.AttributeKey;
import io.moquette.server.ServerChannel;
/** /**
* *
* @author andrea * @author andrea
*/ */
public class NettyChannel implements ServerChannel { public class NettyChannel {
private ChannelHandlerContext m_channel; private ChannelHandlerContext m_channel;
@@ -52,28 +52,28 @@ public class NettyMQTTHandler extends ChannelInboundHandlerAdapter {
m_processor.processConnect(ctx.channel(), (ConnectMessage) msg); m_processor.processConnect(ctx.channel(), (ConnectMessage) msg);
break; break;
case SUBSCRIBE: case SUBSCRIBE:
m_processor.processSubscribe(new NettyChannel(ctx), (SubscribeMessage) msg); m_processor.processSubscribe(ctx.channel(), (SubscribeMessage) msg);
break; break;
case UNSUBSCRIBE: case UNSUBSCRIBE:
m_processor.processUnsubscribe(new NettyChannel(ctx), (UnsubscribeMessage) msg); m_processor.processUnsubscribe(ctx.channel(), (UnsubscribeMessage) msg);
break; break;
case PUBLISH: case PUBLISH:
m_processor.processPublish(new NettyChannel(ctx), (PublishMessage) msg); m_processor.processPublish(ctx.channel(), (PublishMessage) msg);
break; break;
case PUBREC: case PUBREC:
m_processor.processPubRec(new NettyChannel(ctx), (PubRecMessage) msg); m_processor.processPubRec(ctx.channel(), (PubRecMessage) msg);
break; break;
case PUBCOMP: case PUBCOMP:
m_processor.processPubComp(new NettyChannel(ctx), (PubCompMessage) msg); m_processor.processPubComp(ctx.channel(), (PubCompMessage) msg);
break; break;
case PUBREL: case PUBREL:
m_processor.processPubRel(new NettyChannel(ctx), (PubRelMessage) msg); m_processor.processPubRel(ctx.channel(), (PubRelMessage) msg);
break; break;
case DISCONNECT: case DISCONNECT:
m_processor.processDisconnect(new NettyChannel(ctx)); m_processor.processDisconnect(ctx.channel());
break; break;
case PUBACK: case PUBACK:
m_processor.processPubAck(new NettyChannel(ctx), (PubAckMessage) msg); m_processor.processPubAck(ctx.channel(), (PubAckMessage) msg);
break; break;
case PINGREQ: case PINGREQ:
PingRespMessage pingResp = new PingRespMessage(); PingRespMessage pingResp = new PingRespMessage();
@@ -27,13 +27,13 @@ import io.netty.util.AttributeKey;
*/ */
public class NettyUtils { public class NettyUtils {
public static Object getAttribute(ChannelHandlerContext channel, AttributeKey<Object> key) { public static Object getAttribute(ChannelHandlerContext ctx, AttributeKey<Object> key) {
Attribute<Object> attr = channel.attr(key); Attribute<Object> attr = ctx.channel().attr(key);
return attr.get(); return attr.get();
} }
public static void setAttribute(ChannelHandlerContext channel, AttributeKey<Object> key, Object value) { public static void setAttribute(ChannelHandlerContext ctx, AttributeKey<Object> key, Object value) {
Attribute<Object> attr = channel.attr(key); Attribute<Object> attr = ctx.channel().attr(key);
attr.set(value); attr.set(value);
} }
@@ -21,7 +21,6 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import io.moquette.server.ConnectionDescriptor; import io.moquette.server.ConnectionDescriptor;
import io.moquette.server.ServerChannel;
import io.moquette.server.netty.NettyChannel; import io.moquette.server.netty.NettyChannel;
import io.moquette.spi.ClientSession; import io.moquette.spi.ClientSession;
import io.moquette.spi.IMatchingCondition; import io.moquette.spi.IMatchingCondition;
@@ -142,7 +141,7 @@ public class ProtocolProcessor {
ConnAckMessage badProto = new ConnAckMessage(); ConnAckMessage badProto = new ConnAckMessage();
badProto.setReturnCode(ConnAckMessage.UNNACEPTABLE_PROTOCOL_VERSION); badProto.setReturnCode(ConnAckMessage.UNNACEPTABLE_PROTOCOL_VERSION);
LOG.warn("processConnect sent bad proto ConnAck"); LOG.warn("processConnect sent bad proto ConnAck");
session.write(badProto); session.writeAndFlush(badProto);
session.close(); session.close();
return; return;
} }
@@ -150,7 +149,7 @@ public class ProtocolProcessor {
if (msg.getClientID() == null || msg.getClientID().length() == 0) { if (msg.getClientID() == null || msg.getClientID().length() == 0) {
ConnAckMessage okResp = new ConnAckMessage(); ConnAckMessage okResp = new ConnAckMessage();
okResp.setReturnCode(ConnAckMessage.IDENTIFIER_REJECTED); okResp.setReturnCode(ConnAckMessage.IDENTIFIER_REJECTED);
session.write(okResp); session.writeAndFlush(okResp);
m_interceptor.notifyClientConnected(msg); m_interceptor.notifyClientConnected(msg);
return; return;
} }
@@ -166,6 +165,7 @@ public class ProtocolProcessor {
} }
if (!m_authenticator.checkValid(msg.getUsername(), pwd)) { if (!m_authenticator.checkValid(msg.getUsername(), pwd)) {
failedCredentials(session); failedCredentials(session);
session.close();
return; return;
} }
session.attr(NettyChannel.ATTR_KEY_USERNAME).set(msg.getUsername()); session.attr(NettyChannel.ATTR_KEY_USERNAME).set(msg.getUsername());
@@ -217,7 +217,7 @@ public class ProtocolProcessor {
if (!msg.isCleanSession() && isSessionAlreadyStored) { if (!msg.isCleanSession() && isSessionAlreadyStored) {
okResp.setSessionPresent(true); okResp.setSessionPresent(true);
} }
session.write(okResp); session.writeAndFlush(okResp);
m_interceptor.notifyClientConnected(msg); m_interceptor.notifyClientConnected(msg);
if (!isSessionAlreadyStored) { if (!isSessionAlreadyStored) {
@@ -247,7 +247,7 @@ public class ProtocolProcessor {
private void failedCredentials(Channel session) { private void failedCredentials(Channel session) {
ConnAckMessage okResp = new ConnAckMessage(); ConnAckMessage okResp = new ConnAckMessage();
okResp.setReturnCode(ConnAckMessage.BAD_USERNAME_OR_PASSWORD); okResp.setReturnCode(ConnAckMessage.BAD_USERNAME_OR_PASSWORD);
session.write(okResp); session.writeAndFlush(okResp);
} }
/** /**
@@ -270,8 +270,8 @@ public class ProtocolProcessor {
} }
} }
public void processPubAck(ServerChannel session, PubAckMessage msg) { public void processPubAck(Channel session, PubAckMessage msg) {
String clientID = (String) session.getAttribute(NettyChannel.ATTR_KEY_CLIENTID); String clientID = (String) session.attr(NettyChannel.ATTR_KEY_CLIENTID).get();
int messageID = msg.getMessageID(); int messageID = msg.getMessageID();
//Remove the message from message store //Remove the message from message store
ClientSession targetSession = m_sessionsStore.sessionForClient(clientID); ClientSession targetSession = m_sessionsStore.sessionForClient(clientID);
@@ -535,14 +535,14 @@ public class ProtocolProcessor {
LOG.debug("topic {} doesn't have read credentials", topic); LOG.debug("topic {} doesn't have read credentials", topic);
return; return;
} }
session.write(pubMessage); session.writeAndFlush(pubMessage); //Or writeAdnFlush but flush is costly!!
} }
private void sendPubRec(String clientID, int messageID) { private void sendPubRec(String clientID, int messageID) {
LOG.trace("PUB <--PUBREC-- SRV sendPubRec invoked for clientID {} with messageID {}", clientID, messageID); LOG.trace("PUB <--PUBREC-- SRV sendPubRec invoked for clientID {} with messageID {}", clientID, messageID);
PubRecMessage pubRecMessage = new PubRecMessage(); PubRecMessage pubRecMessage = new PubRecMessage();
pubRecMessage.setMessageID(messageID); pubRecMessage.setMessageID(messageID);
m_clientIDs.get(clientID).session.write(pubRecMessage); m_clientIDs.get(clientID).session.writeAndFlush(pubRecMessage);
} }
private void sendPubAck(String clientId, int messageID) { private void sendPubAck(String clientId, int messageID) {
@@ -558,7 +558,7 @@ public class ProtocolProcessor {
if (m_clientIDs.get(clientId) == null) { if (m_clientIDs.get(clientId) == null) {
throw new RuntimeException(String.format("Can't find a ConnectionDescriptor for client %s in cache %s", clientId, m_clientIDs)); throw new RuntimeException(String.format("Can't find a ConnectionDescriptor for client %s in cache %s", clientId, m_clientIDs));
} }
m_clientIDs.get(clientId).session.write(pubAckMessage); m_clientIDs.get(clientId).session.writeAndFlush(pubAckMessage);
} catch(Throwable t) { } catch(Throwable t) {
LOG.error(null, t); LOG.error(null, t);
} }
@@ -568,8 +568,8 @@ public class ProtocolProcessor {
* Second phase of a publish QoS2 protocol, sent by publisher to the broker. Search the stored message and publish * Second phase of a publish QoS2 protocol, sent by publisher to the broker. Search the stored message and publish
* to all interested subscribers. * to all interested subscribers.
* */ * */
public void processPubRel(ServerChannel session, PubRelMessage msg) { public void processPubRel(Channel session, PubRelMessage msg) {
String clientID = (String) session.getAttribute(NettyChannel.ATTR_KEY_CLIENTID); String clientID = (String) session.attr(NettyChannel.ATTR_KEY_CLIENTID).get();
int messageID = msg.getMessageID(); int messageID = msg.getMessageID();
LOG.debug("PUB --PUBREL--> SRV processPubRel invoked for clientID {} ad messageID {}", clientID, messageID); LOG.debug("PUB --PUBREL--> SRV processPubRel invoked for clientID {} ad messageID {}", clientID, messageID);
ClientSession targetSession = m_sessionsStore.sessionForClient(clientID); ClientSession targetSession = m_sessionsStore.sessionForClient(clientID);
@@ -594,11 +594,11 @@ public class ProtocolProcessor {
PubCompMessage pubCompMessage = new PubCompMessage(); PubCompMessage pubCompMessage = new PubCompMessage();
pubCompMessage.setMessageID(messageID); pubCompMessage.setMessageID(messageID);
m_clientIDs.get(clientID).session.write(pubCompMessage); m_clientIDs.get(clientID).session.writeAndFlush(pubCompMessage);
} }
public void processPubRec(ServerChannel session, PubRecMessage msg) { public void processPubRec(Channel session, PubRecMessage msg) {
String clientID = (String) session.getAttribute(NettyChannel.ATTR_KEY_CLIENTID); String clientID = (String) session.attr(NettyChannel.ATTR_KEY_CLIENTID).get();
int messageID = msg.getMessageID(); int messageID = msg.getMessageID();
ClientSession targetSession = m_sessionsStore.sessionForClient(clientID); ClientSession targetSession = m_sessionsStore.sessionForClient(clientID);
verifyToActivate(clientID, targetSession); verifyToActivate(clientID, targetSession);
@@ -611,11 +611,11 @@ public class ProtocolProcessor {
pubRelMessage.setMessageID(messageID); pubRelMessage.setMessageID(messageID);
pubRelMessage.setQos(AbstractMessage.QOSType.LEAST_ONE); pubRelMessage.setQos(AbstractMessage.QOSType.LEAST_ONE);
session.write(pubRelMessage); session.writeAndFlush(pubRelMessage);
} }
public void processPubComp(ServerChannel session, PubCompMessage msg) { public void processPubComp(Channel session, PubCompMessage msg) {
String clientID = (String) session.getAttribute(NettyChannel.ATTR_KEY_CLIENTID); String clientID = (String) session.attr(NettyChannel.ATTR_KEY_CLIENTID).get();
int messageID = msg.getMessageID(); int messageID = msg.getMessageID();
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
@@ -624,15 +624,15 @@ public class ProtocolProcessor {
targetSession.secondPhaseAcknowledged(messageID); targetSession.secondPhaseAcknowledged(messageID);
} }
public void processDisconnect(ServerChannel session) throws InterruptedException { public void processDisconnect(Channel session) throws InterruptedException {
String clientID = (String) session.getAttribute(NettyChannel.ATTR_KEY_CLIENTID); String clientID = (String) session.attr(NettyChannel.ATTR_KEY_CLIENTID).get();
boolean cleanSession = (Boolean) session.getAttribute(NettyChannel.ATTR_KEY_CLEANSESSION); boolean cleanSession = (Boolean) session.attr(NettyChannel.ATTR_KEY_CLEANSESSION).get();
LOG.info("DISCONNECT client <{}> with clean session {}", clientID, cleanSession); LOG.info("DISCONNECT client <{}> with clean session {}", clientID, cleanSession);
ClientSession clientSession = m_sessionsStore.sessionForClient(clientID); ClientSession clientSession = m_sessionsStore.sessionForClient(clientID);
clientSession.disconnect(); clientSession.disconnect();
m_clientIDs.remove(clientID); m_clientIDs.remove(clientID);
session.close(true); session.close();
//cleanup the will store //cleanup the will store
m_willStore.remove(clientID); m_willStore.remove(clientID);
@@ -691,7 +691,7 @@ public class ProtocolProcessor {
ackMessage.setMessageID(messageID); ackMessage.setMessageID(messageID);
LOG.info("replying with UnsubAck to MSG ID {}", messageID); LOG.info("replying with UnsubAck to MSG ID {}", messageID);
session.write(ackMessage); session.writeAndFlush(ackMessage);
} }
public void processSubscribe(Channel session, SubscribeMessage msg) { public void processSubscribe(Channel session, SubscribeMessage msg) {
@@ -721,7 +721,7 @@ public class ProtocolProcessor {
if (LOG.isTraceEnabled()) { if (LOG.isTraceEnabled()) {
LOG.trace("subscription tree {}", subscriptions.dumpTree()); LOG.trace("subscription tree {}", subscriptions.dumpTree());
} }
session.write(ackMessage); session.writeAndFlush(ackMessage);
//fire the publish //fire the publish
for(Subscription subscription : newSubscriptions) { for(Subscription subscription : newSubscriptions) {
@@ -33,9 +33,6 @@ import java.util.concurrent.TimeUnit;
import static org.junit.Assert.*; import static org.junit.Assert.*;
/**
* Created by andrea on 08/12/15.
*/
public class ServerIntegrationEmbeddedPublishTest { public class ServerIntegrationEmbeddedPublishTest {
private static final Logger LOG = LoggerFactory.getLogger(ServerIntegrationEmbeddedPublishTest.class); private static final Logger LOG = LoggerFactory.getLogger(ServerIntegrationEmbeddedPublishTest.class);
@@ -451,7 +451,7 @@ public class ServerIntegrationPahoTest {
clientXA.subscribe("topic", 0); clientXA.subscribe("topic", 0);
MqttClient clientXB = createClient("publisher", "X"); MqttClient clientXB = createClient("publisher", "X");
clientXB.publish("topic", "Hello".getBytes(), 2, true); clientXB.publish("topic", "Hello".getBytes(), 2, false);
TestCallback cbSubscriber2 = new TestCallback(); TestCallback cbSubscriber2 = new TestCallback();
MqttClient clientYA = createClient("subscriber", "Y", cbSubscriber2); MqttClient clientYA = createClient("subscriber", "Y", cbSubscriber2);
@@ -1,78 +0,0 @@
/*
* Copyright (c) 2012-2015 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* 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.util.AttributeKey;
import io.moquette.proto.messages.AbstractMessage;
import io.moquette.proto.messages.ConnAckMessage;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author andrea
*/
public class DummyChannel extends EmbeddedChannel {
AbstractMessage m_receivedMessage;
byte m_returnCode;
private boolean m_channelClosed = false;
private Map<Object, Object> m_attributes = new HashMap<>();
public Object getAttribute(AttributeKey<Object> key) {
return m_attributes.get(key);
}
public void setAttribute(AttributeKey<Object> key, Object value) {
m_attributes.put(key, value);
}
public void setIdleTime(int idleTime) {
}
public void close(boolean immediately) {
m_channelClosed = true;
}
boolean isClosed() {
return this.m_channelClosed;
}
// public void write(Object value) {
// try {
// m_receivedMessage = (AbstractMessage) value;
// if (m_receivedMessage instanceof ConnAckMessage) {
// ConnAckMessage buf = (ConnAckMessage) m_receivedMessage;
// m_returnCode = buf.getReturnCode();
// }
// } catch (Exception ex) {
// throw new AssertionError("Wrong return code");
// }
// }
public byte getReturnCode() {
return m_returnCode;
}
public AbstractMessage getReceivedMessage() {
return m_receivedMessage;
}
}
@@ -1,7 +0,0 @@
package io.moquette.spi.impl;
/**
* Created by andrea on 6/7/15.
*/
public class DummyChannelHandlerContext {
}
@@ -16,7 +16,6 @@
import io.netty.util.AttributeKey; import io.netty.util.AttributeKey;
import io.moquette.proto.messages.AbstractMessage; import io.moquette.proto.messages.AbstractMessage;
import io.moquette.server.ServerChannel;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@@ -24,7 +23,7 @@ import java.util.Map;
/** /**
* This a synchronous channel that avoid output ring buffer from Processor * This a synchronous channel that avoid output ring buffer from Processor
*/ */
class MockReceiverChannel implements ServerChannel { class MockReceiverChannel /*implements ServerChannel*/ {
// byte m_returnCode; // byte m_returnCode;
AbstractMessage m_receivedMessage; AbstractMessage m_receivedMessage;
private Map<Object, Object> m_attributes = new HashMap<>(); private Map<Object, Object> m_attributes = new HashMap<>();
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2012-2015 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.moquette.spi.impl;
import io.moquette.proto.messages.ConnAckMessage;
import io.moquette.proto.messages.SubAckMessage;
import io.netty.channel.Channel;
import io.netty.channel.embedded.EmbeddedChannel;
import static io.moquette.proto.messages.ConnAckMessage.CONNECTION_ACCEPTED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* Some useful assertions used by Netty's EmbeddedChannel in tests.
*/
class NettyChannelAssertions {
static void assertEqualsConnAck(byte expectedCode, Object connAck) {
assertTrue(connAck instanceof ConnAckMessage);
ConnAckMessage connAckMsg = (ConnAckMessage) connAck;
assertEquals(expectedCode, connAckMsg.getReturnCode());
}
static void assertConnAckAccepted(EmbeddedChannel channel) {
channel.flush();
assertEqualsConnAck(CONNECTION_ACCEPTED, channel.readOutbound());
}
static void assertEqualsSubAck(/*byte expectedCode,*/ Object subAck) {
assertTrue(subAck instanceof SubAckMessage);
//SubAckMessage connAckMsg = (SubAckMessage) connAck;
//assertEquals(expectedCode, connAckMsg.getReturnCode());
}
}
@@ -34,9 +34,7 @@ import org.junit.Test;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.*; import java.util.*;
import java.util.concurrent.CountDownLatch; import static io.moquette.spi.impl.NettyChannelAssertions.assertConnAckAccepted;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
@@ -59,7 +57,7 @@ public class ProtocolProcessorTest {
final static List<InterceptHandler> EMPTY_OBSERVERS = Collections.emptyList(); final static List<InterceptHandler> EMPTY_OBSERVERS = Collections.emptyList();
final static BrokerInterceptor NO_OBSERVERS_INTERCEPTOR = new BrokerInterceptor(EMPTY_OBSERVERS); final static BrokerInterceptor NO_OBSERVERS_INTERCEPTOR = new BrokerInterceptor(EMPTY_OBSERVERS);
DummyChannel m_session; EmbeddedChannel m_session;
ConnectMessage connMsg; ConnectMessage connMsg;
ProtocolProcessor m_processor; ProtocolProcessor m_processor;
@@ -73,7 +71,7 @@ public class ProtocolProcessorTest {
connMsg = new ConnectMessage(); connMsg = new ConnectMessage();
connMsg.setProtocolVersion((byte) 0x03); connMsg.setProtocolVersion((byte) 0x03);
m_session = new DummyChannel(); 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); Thread.sleep(300);
@@ -96,7 +94,7 @@ public class ProtocolProcessorTest {
@Test @Test
public void testPublish() throws InterruptedException { public void testPublishToItself() throws InterruptedException {
final Subscription subscription = new Subscription(FAKE_CLIENT_ID, final Subscription subscription = new Subscription(FAKE_CLIENT_ID,
FAKE_TOPIC, AbstractMessage.QOSType.MOST_ONE); FAKE_TOPIC, AbstractMessage.QOSType.MOST_ONE);
@@ -132,11 +130,11 @@ public class ProtocolProcessorTest {
msg.setQos(QOSType.MOST_ONE); msg.setQos(QOSType.MOST_ONE);
msg.setPayload(buffer); msg.setPayload(buffer);
msg.setRetainFlag(false); msg.setRetainFlag(false);
m_session.setAttribute(NettyChannel.ATTR_KEY_CLIENTID, "FakeCLI"); m_session.attr(NettyChannel.ATTR_KEY_USERNAME).set("FakeCLI");
m_processor.processPublish(m_session, msg); m_processor.processPublish(m_session, msg);
//Verify //Verify
assertNotNull(m_session.getReceivedMessage()); assertNotNull(m_session.readOutbound());
//TODO check received message attributes //TODO check received message attributes
} }
@@ -171,6 +169,7 @@ public class ProtocolProcessorTest {
connectMessage.setClientID(FAKE_CLIENT_ID); connectMessage.setClientID(FAKE_CLIENT_ID);
connectMessage.setCleanSession(true); connectMessage.setCleanSession(true);
m_processor.processConnect(firstReceiverSession, connectMessage); m_processor.processConnect(firstReceiverSession, connectMessage);
assertConnAckAccepted(firstReceiverSession);
//connect the second fake subscriber //connect the second fake subscriber
EmbeddedChannel secondReceiverSession = new EmbeddedChannel(); EmbeddedChannel secondReceiverSession = new EmbeddedChannel();
@@ -180,6 +179,7 @@ public class ProtocolProcessorTest {
connectMessage2.setCleanSession(true); connectMessage2.setCleanSession(true);
connectMessage2.setCleanSession(true); connectMessage2.setCleanSession(true);
m_processor.processConnect(secondReceiverSession, connectMessage2); m_processor.processConnect(secondReceiverSession, connectMessage2);
assertConnAckAccepted(secondReceiverSession);
//Exercise //Exercise
ByteBuffer buffer = ByteBuffer.allocate(5).put("Hello".getBytes()); ByteBuffer buffer = ByteBuffer.allocate(5).put("Hello".getBytes());
@@ -189,17 +189,17 @@ public class ProtocolProcessorTest {
msg.setQos(QOSType.MOST_ONE); msg.setQos(QOSType.MOST_ONE);
msg.setPayload(buffer); msg.setPayload(buffer);
msg.setRetainFlag(false); msg.setRetainFlag(false);
m_session.setAttribute(NettyChannel.ATTR_KEY_CLIENTID, "FakeCLI"); m_session.attr(NettyChannel.ATTR_KEY_USERNAME).set("FakeCLI");
m_processor.processPublish(m_session, msg); m_processor.processPublish(m_session, msg);
//Verify //Verify
Thread.sleep(100); //ugly but we depend on the asynch that pull data from back disruptor PublishMessage pub2FirstSubscriber = (PublishMessage) firstReceiverSession.readOutbound();
PublishMessage pub2FirstSubscriber = (PublishMessage) firstReceiverSession.getMessage();
assertNotNull(pub2FirstSubscriber); assertNotNull(pub2FirstSubscriber);
String firstMessageContent = DebugUtils.payload2Str(pub2FirstSubscriber.getPayload()); String firstMessageContent = DebugUtils.payload2Str(pub2FirstSubscriber.getPayload());
assertEquals("Hello", firstMessageContent); assertEquals("Hello", firstMessageContent);
PublishMessage pub2SecondSubscriber = (PublishMessage) secondReceiverSession.getMessage(); PublishMessage pub2SecondSubscriber = (PublishMessage) secondReceiverSession.readOutbound();
assertNotNull(pub2SecondSubscriber); assertNotNull(pub2SecondSubscriber);
String secondMessageContent = DebugUtils.payload2Str(pub2SecondSubscriber.getPayload()); String secondMessageContent = DebugUtils.payload2Str(pub2SecondSubscriber.getPayload());
assertEquals("Hello", secondMessageContent); assertEquals("Hello", secondMessageContent);
@@ -210,13 +210,13 @@ public class ProtocolProcessorTest {
//Exercise //Exercise
SubscribeMessage msg = new SubscribeMessage(); SubscribeMessage msg = new SubscribeMessage();
msg.addSubscription(new SubscribeMessage.Couple(AbstractMessage.QOSType.MOST_ONE.byteValue(), FAKE_TOPIC)); msg.addSubscription(new SubscribeMessage.Couple(AbstractMessage.QOSType.MOST_ONE.byteValue(), FAKE_TOPIC));
m_session.setAttribute(NettyChannel.ATTR_KEY_CLIENTID, FAKE_CLIENT_ID); m_session.attr(NettyChannel.ATTR_KEY_CLIENTID).set(FAKE_CLIENT_ID);
m_session.setAttribute(NettyChannel.ATTR_KEY_CLEANSESSION, false); m_session.attr(NettyChannel.ATTR_KEY_CLEANSESSION).set(false);
m_sessionStore.createNewSession(FAKE_CLIENT_ID, false); m_sessionStore.createNewSession(FAKE_CLIENT_ID, false);
m_processor.processSubscribe(m_session, msg/*, FAKE_CLIENT_ID, false*/); m_processor.processSubscribe(m_session, msg);
//Verify //Verify
assertTrue(m_session.getReceivedMessage() instanceof SubAckMessage); assertTrue(m_session.readOutbound() instanceof SubAckMessage);
Subscription expectedSubscription = new Subscription(FAKE_CLIENT_ID, FAKE_TOPIC, AbstractMessage.QOSType.MOST_ONE); Subscription expectedSubscription = new Subscription(FAKE_CLIENT_ID, FAKE_TOPIC, AbstractMessage.QOSType.MOST_ONE);
assertTrue(subscriptions.contains(expectedSubscription)); assertTrue(subscriptions.contains(expectedSubscription));
} }
@@ -225,8 +225,8 @@ public class ProtocolProcessorTest {
public void testDoubleSubscribe() { public void testDoubleSubscribe() {
SubscribeMessage msg = new SubscribeMessage(); SubscribeMessage msg = new SubscribeMessage();
msg.addSubscription(new SubscribeMessage.Couple(AbstractMessage.QOSType.MOST_ONE.byteValue(), FAKE_TOPIC)); msg.addSubscription(new SubscribeMessage.Couple(AbstractMessage.QOSType.MOST_ONE.byteValue(), FAKE_TOPIC));
m_session.setAttribute(NettyChannel.ATTR_KEY_CLIENTID, FAKE_CLIENT_ID); m_session.attr(NettyChannel.ATTR_KEY_CLIENTID).set(FAKE_CLIENT_ID);
m_session.setAttribute(NettyChannel.ATTR_KEY_CLEANSESSION, false); m_session.attr(NettyChannel.ATTR_KEY_CLEANSESSION).set(false);
m_sessionStore.createNewSession(FAKE_CLIENT_ID, false); m_sessionStore.createNewSession(FAKE_CLIENT_ID, false);
assertEquals(0, subscriptions.size()); assertEquals(0, subscriptions.size());
@@ -246,8 +246,8 @@ public class ProtocolProcessorTest {
public void testSubscribeWithBadFormattedTopic() { public void testSubscribeWithBadFormattedTopic() {
SubscribeMessage msg = new SubscribeMessage(); SubscribeMessage msg = new SubscribeMessage();
msg.addSubscription(new SubscribeMessage.Couple(AbstractMessage.QOSType.MOST_ONE.byteValue(), BAD_FORMATTED_TOPIC)); msg.addSubscription(new SubscribeMessage.Couple(AbstractMessage.QOSType.MOST_ONE.byteValue(), BAD_FORMATTED_TOPIC));
m_session.setAttribute(NettyChannel.ATTR_KEY_CLIENTID, FAKE_CLIENT_ID); m_session.attr(NettyChannel.ATTR_KEY_CLIENTID).set(FAKE_CLIENT_ID);
m_session.setAttribute(NettyChannel.ATTR_KEY_CLEANSESSION, false); m_session.attr(NettyChannel.ATTR_KEY_CLEANSESSION).set(false);
m_sessionStore.createNewSession(FAKE_CLIENT_ID, false); m_sessionStore.createNewSession(FAKE_CLIENT_ID, false);
assertEquals(0, subscriptions.size()); assertEquals(0, subscriptions.size());
@@ -256,8 +256,9 @@ public class ProtocolProcessorTest {
//Verify //Verify
assertEquals(0, subscriptions.size()); assertEquals(0, subscriptions.size());
assertTrue(m_session.getReceivedMessage() instanceof SubAckMessage); Object recvSubAckMessage = m_session.readOutbound();
List<QOSType> qosSubAcked = ((SubAckMessage) m_session.getReceivedMessage()).types(); assertTrue(recvSubAckMessage instanceof SubAckMessage);
List<QOSType> qosSubAcked = ((SubAckMessage)recvSubAckMessage).types();
assertEquals(1, qosSubAcked.size()); assertEquals(1, qosSubAcked.size());
assertEquals(QOSType.FAILURE, qosSubAcked.get(0)); assertEquals(QOSType.FAILURE, qosSubAcked.get(0));
} }
@@ -270,40 +271,19 @@ public class ProtocolProcessorTest {
UnsubscribeMessage msg = new UnsubscribeMessage(); UnsubscribeMessage msg = new UnsubscribeMessage();
msg.setMessageID(1); msg.setMessageID(1);
msg.addTopicFilter(BAD_FORMATTED_TOPIC); msg.addTopicFilter(BAD_FORMATTED_TOPIC);
m_session.setAttribute(NettyChannel.ATTR_KEY_CLIENTID, FAKE_CLIENT_ID); m_session.attr(NettyChannel.ATTR_KEY_CLIENTID).set(FAKE_CLIENT_ID);
m_session.setAttribute(NettyChannel.ATTR_KEY_CLEANSESSION, false); m_session.attr(NettyChannel.ATTR_KEY_CLEANSESSION).set(false);
//Exercise //Exercise
m_processor.processUnsubscribe(m_session, msg); m_processor.processUnsubscribe(m_session, msg);
//Verify //Verify
assertTrue(m_session.isClosed()); assertFalse("If client unsubscribe with bad topic than channel must be closed", m_session.isOpen());
} }
@Test @Test
public void testPublishOfRetainedMessage_afterNewSubscription() throws Exception { public void testPublishOfRetainedMessage_afterNewSubscription() throws Exception {
final CountDownLatch publishRecvSignal = new CountDownLatch(1);
m_session = new DummyChannel() {
@Override
public void write(Object value) {
try {
System.out.println("filterReceived class " + value.getClass().getName());
if (value instanceof PublishMessage) {
m_receivedMessage = (AbstractMessage) value;
publishRecvSignal.countDown();
}
if (m_receivedMessage instanceof ConnAckMessage) {
ConnAckMessage buf = (ConnAckMessage) m_receivedMessage;
m_returnCode = buf.getReturnCode();
}
} catch (Exception ex) {
throw new AssertionError("Wrong return code");
}
}
};
//simulate a connect that register a clientID to an IoSession //simulate a connect that register a clientID to an IoSession
final Subscription subscription = new Subscription(FAKE_PUBLISHER_ID, final Subscription subscription = new Subscription(FAKE_PUBLISHER_ID,
FAKE_TOPIC, AbstractMessage.QOSType.MOST_ONE); FAKE_TOPIC, AbstractMessage.QOSType.MOST_ONE);
@@ -330,15 +310,16 @@ public class ProtocolProcessorTest {
connectMessage.setProtocolVersion((byte) 3); connectMessage.setProtocolVersion((byte) 3);
connectMessage.setCleanSession(true); connectMessage.setCleanSession(true);
m_processor.processConnect(m_session, connectMessage); m_processor.processConnect(m_session, connectMessage);
assertConnAckAccepted(m_session);
ByteBuffer buffer = ByteBuffer.allocate(5).put("Hello".getBytes()); ByteBuffer buffer = ByteBuffer.allocate(5).put("Hello".getBytes());
PublishMessage pubmsg = new PublishMessage(); PublishMessage pubmsg = new PublishMessage();
pubmsg.setTopicName(FAKE_TOPIC); pubmsg.setTopicName(FAKE_TOPIC);
pubmsg.setQos(QOSType.MOST_ONE); pubmsg.setQos(QOSType.MOST_ONE);
pubmsg.setPayload(buffer); pubmsg.setPayload(buffer);
pubmsg.setRetainFlag(true); pubmsg.setRetainFlag(true);
m_session.setAttribute(NettyChannel.ATTR_KEY_CLIENTID, FAKE_PUBLISHER_ID); m_session.attr(NettyChannel.ATTR_KEY_CLIENTID).set(FAKE_PUBLISHER_ID);
m_processor.processPublish(m_session, pubmsg); m_processor.processPublish(m_session, pubmsg);
m_session.setAttribute(NettyChannel.ATTR_KEY_CLEANSESSION, false); m_session.attr(NettyChannel.ATTR_KEY_CLEANSESSION).set(false);
//Exercise //Exercise
SubscribeMessage msg = new SubscribeMessage(); SubscribeMessage msg = new SubscribeMessage();
@@ -347,11 +328,10 @@ public class ProtocolProcessorTest {
//Verify //Verify
//wait the latch //wait the latch
assertTrue(publishRecvSignal.await(1, TimeUnit.SECONDS)); //no timeout Object pubMessage = m_session.readOutbound();
assertNotNull(m_session.getReceivedMessage()); assertNotNull(pubMessage);
assertTrue(m_session.getReceivedMessage() instanceof PublishMessage); assertTrue(pubMessage instanceof PublishMessage);
PublishMessage pubMessage = (PublishMessage) m_session.getReceivedMessage(); assertEquals(FAKE_TOPIC, ((PublishMessage) pubMessage).getTopicName());
assertEquals(FAKE_TOPIC, pubMessage.getTopicName());
} }
@Test @Test
@@ -397,11 +377,11 @@ public class ProtocolProcessorTest {
msg.setQos(QOSType.MOST_ONE); msg.setQos(QOSType.MOST_ONE);
msg.setPayload(buffer); msg.setPayload(buffer);
msg.setRetainFlag(true); msg.setRetainFlag(true);
m_session.setAttribute(NettyChannel.ATTR_KEY_CLIENTID, "Publisher"); m_session.attr(NettyChannel.ATTR_KEY_CLIENTID).set("Publisher");
m_processor.processPublish(m_session, msg); m_processor.processPublish(m_session, msg);
//Verify no message is received //Verify no message is received
assertNull(m_session.getReceivedMessage()); assertNull(m_session.readOutbound());
} }
@@ -424,11 +404,11 @@ public class ProtocolProcessorTest {
msg.setQos(QOSType.MOST_ONE); msg.setQos(QOSType.MOST_ONE);
msg.setPayload(buffer); msg.setPayload(buffer);
msg.setRetainFlag(true); msg.setRetainFlag(true);
m_session.setAttribute(NettyChannel.ATTR_KEY_CLIENTID, "Publisher"); m_session.attr(NettyChannel.ATTR_KEY_CLIENTID).set("Publisher");
m_processor.processPublish(m_session, msg); m_processor.processPublish(m_session, msg);
//Verify no message is received //Verify no message is received
assertNull(m_session.getReceivedMessage()); assertNull(m_session.readOutbound());
} }
@@ -442,7 +422,7 @@ public class ProtocolProcessorTest {
connMsg.setClientID("Publisher"); connMsg.setClientID("Publisher");
m_processor.processConnect(m_session, connMsg); m_processor.processConnect(m_session, connMsg);
//prepare and existing retained store //prepare and existing retained store
m_session.setAttribute(NettyChannel.ATTR_KEY_CLIENTID, "Publisher"); m_session.attr(NettyChannel.ATTR_KEY_CLIENTID).set("Publisher");
ByteBuffer payload = ByteBuffer.allocate(5).put("Hello".getBytes()); ByteBuffer payload = ByteBuffer.allocate(5).put("Hello".getBytes());
PublishMessage msg = new PublishMessage(); PublishMessage msg = new PublishMessage();
msg.setTopicName(FAKE_TOPIC); msg.setTopicName(FAKE_TOPIC);
@@ -16,7 +16,6 @@
package io.moquette.spi.impl; package io.moquette.spi.impl;
import io.moquette.proto.messages.AbstractMessage; import io.moquette.proto.messages.AbstractMessage;
import io.moquette.proto.messages.ConnAckMessage;
import io.moquette.proto.messages.ConnectMessage; import io.moquette.proto.messages.ConnectMessage;
import io.moquette.proto.messages.SubscribeMessage; import io.moquette.proto.messages.SubscribeMessage;
import io.moquette.spi.IMessagesStore; import io.moquette.spi.IMessagesStore;
@@ -25,6 +24,7 @@ import io.moquette.spi.impl.subscriptions.SubscriptionsStore;
import io.moquette.server.netty.NettyChannel; import io.moquette.server.netty.NettyChannel;
import io.moquette.spi.impl.security.PermitAllAuthorizator; import io.moquette.spi.impl.security.PermitAllAuthorizator;
import io.moquette.spi.impl.subscriptions.Subscription; import io.moquette.spi.impl.subscriptions.Subscription;
import io.netty.channel.embedded.EmbeddedChannel;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -32,7 +32,11 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static io.moquette.parser.netty.Utils.VERSION_3_1_1; import static io.moquette.parser.netty.Utils.VERSION_3_1_1;
import static org.junit.Assert.assertEquals; import static io.moquette.proto.messages.ConnAckMessage.BAD_USERNAME_OR_PASSWORD;
import static io.moquette.proto.messages.ConnAckMessage.CONNECTION_ACCEPTED;
import static io.moquette.proto.messages.ConnAckMessage.UNNACEPTABLE_PROTOCOL_VERSION;
import static io.moquette.spi.impl.NettyChannelAssertions.assertEqualsConnAck;
import static io.moquette.spi.impl.NettyChannelAssertions.assertEqualsSubAck;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
@@ -42,7 +46,7 @@ import static org.junit.Assert.assertTrue;
*/ */
public class ProtocolProcessor_CONNECT_Test { public class ProtocolProcessor_CONNECT_Test {
DummyChannel m_session; EmbeddedChannel m_session;
ConnectMessage connMsg; ConnectMessage connMsg;
ProtocolProcessor m_processor; ProtocolProcessor m_processor;
@@ -56,7 +60,7 @@ public class ProtocolProcessor_CONNECT_Test {
connMsg = new ConnectMessage(); connMsg = new ConnectMessage();
connMsg.setProtocolVersion((byte) 0x03); connMsg.setProtocolVersion((byte) 0x03);
m_session = new DummyChannel(); 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); Thread.sleep(300);
@@ -85,7 +89,7 @@ public class ProtocolProcessor_CONNECT_Test {
m_processor.processConnect(m_session, connMsg); m_processor.processConnect(m_session, connMsg);
//Verify //Verify
assertEquals(ConnAckMessage.UNNACEPTABLE_PROTOCOL_VERSION, m_session.getReturnCode()); assertEqualsConnAck(UNNACEPTABLE_PROTOCOL_VERSION, m_session.readOutbound());
} }
@Test @Test
@@ -96,7 +100,7 @@ public class ProtocolProcessor_CONNECT_Test {
m_processor.processConnect(m_session, connMsg); m_processor.processConnect(m_session, connMsg);
//Verify //Verify
assertEquals(ConnAckMessage.CONNECTION_ACCEPTED, m_session.getReturnCode()); assertEqualsConnAck(CONNECTION_ACCEPTED, m_session.readOutbound());
} }
@Test @Test
@@ -112,7 +116,7 @@ public class ProtocolProcessor_CONNECT_Test {
m_processor.processConnect(m_session, connMsg); m_processor.processConnect(m_session, connMsg);
//Verify //Verify
assertEquals(ConnAckMessage.CONNECTION_ACCEPTED, m_session.getReturnCode()); assertEqualsConnAck(CONNECTION_ACCEPTED, m_session.readOutbound());
//TODO verify the call //TODO verify the call
/*verify(mockedMessaging).publish(eq("topic"), eq("Topic message".getBytes()), /*verify(mockedMessaging).publish(eq("topic"), eq("Topic message".getBytes()),
any(AbstractMessage.QOSType.class), anyBoolean(), eq("123"), any(IoSession.class));*/ any(AbstractMessage.QOSType.class), anyBoolean(), eq("123"), any(IoSession.class));*/
@@ -130,7 +134,7 @@ public class ProtocolProcessor_CONNECT_Test {
m_processor.processConnect(m_session, connMsg); m_processor.processConnect(m_session, connMsg);
//Verify //Verify
assertEquals(ConnAckMessage.CONNECTION_ACCEPTED, m_session.getReturnCode()); assertEqualsConnAck(CONNECTION_ACCEPTED, m_session.readOutbound());
} }
@Test @Test
@@ -144,7 +148,7 @@ public class ProtocolProcessor_CONNECT_Test {
m_processor.processConnect(m_session, connMsg); m_processor.processConnect(m_session, connMsg);
//Verify //Verify
assertEquals(ConnAckMessage.BAD_USERNAME_OR_PASSWORD, m_session.getReturnCode()); assertEqualsConnAck(BAD_USERNAME_OR_PASSWORD, m_session.readOutbound());
} }
@Test @Test
@@ -159,7 +163,7 @@ public class ProtocolProcessor_CONNECT_Test {
m_processor.processConnect(m_session, connMsg); m_processor.processConnect(m_session, connMsg);
//Verify //Verify
assertEquals(ConnAckMessage.BAD_USERNAME_OR_PASSWORD, m_session.getReturnCode()); assertEqualsConnAck(BAD_USERNAME_OR_PASSWORD, m_session.readOutbound());
} }
@Test @Test
@@ -171,7 +175,7 @@ public class ProtocolProcessor_CONNECT_Test {
m_processor.processConnect(m_session, connMsg); m_processor.processConnect(m_session, connMsg);
//Verify //Verify
assertEquals(ConnAckMessage.BAD_USERNAME_OR_PASSWORD, m_session.getReturnCode()); assertEqualsConnAck(BAD_USERNAME_OR_PASSWORD, m_session.readOutbound());
} }
@Test @Test
@@ -185,7 +189,7 @@ public class ProtocolProcessor_CONNECT_Test {
m_processor.processConnect(m_session, connMsg); m_processor.processConnect(m_session, connMsg);
//Verify //Verify
assertEquals(ConnAckMessage.BAD_USERNAME_OR_PASSWORD, m_session.getReturnCode()); assertEqualsConnAck(BAD_USERNAME_OR_PASSWORD, m_session.readOutbound());
} }
@Test @Test
@@ -197,7 +201,7 @@ public class ProtocolProcessor_CONNECT_Test {
m_processor.processConnect(m_session, connMsg); m_processor.processConnect(m_session, connMsg);
//Verify //Verify
assertEquals(ConnAckMessage.CONNECTION_ACCEPTED, m_session.getReturnCode()); assertEqualsConnAck(CONNECTION_ACCEPTED, m_session.readOutbound());
} }
@Test @Test
@@ -209,7 +213,7 @@ public class ProtocolProcessor_CONNECT_Test {
connMsg.setUsername(ProtocolProcessorTest.TEST_USER); connMsg.setUsername(ProtocolProcessorTest.TEST_USER);
connMsg.setPassword(ProtocolProcessorTest.TEST_PWD); connMsg.setPassword(ProtocolProcessorTest.TEST_PWD);
m_processor.processConnect(m_session, connMsg); m_processor.processConnect(m_session, connMsg);
assertEquals(ConnAckMessage.CONNECTION_ACCEPTED, m_session.getReturnCode()); assertEqualsConnAck(CONNECTION_ACCEPTED, m_session.readOutbound());
//create another connect same clientID but with bad credentials //create another connect same clientID but with bad credentials
ConnectMessage evilClientConnMsg = new ConnectMessage(); ConnectMessage evilClientConnMsg = new ConnectMessage();
@@ -219,17 +223,17 @@ public class ProtocolProcessor_CONNECT_Test {
evilClientConnMsg.setPasswordFlag(true); evilClientConnMsg.setPasswordFlag(true);
evilClientConnMsg.setUsername(ProtocolProcessorTest.EVIL_TEST_USER); evilClientConnMsg.setUsername(ProtocolProcessorTest.EVIL_TEST_USER);
evilClientConnMsg.setPassword(ProtocolProcessorTest.EVIL_TEST_PWD); evilClientConnMsg.setPassword(ProtocolProcessorTest.EVIL_TEST_PWD);
DummyChannel evilSession = new DummyChannel(); EmbeddedChannel evilSession = new EmbeddedChannel();
//Exercise //Exercise
m_processor.processConnect(evilSession, evilClientConnMsg); m_processor.processConnect(evilSession, evilClientConnMsg);
//Verify //Verify
//the evil client gets a not auth notification //the evil client gets a not auth notification
assertEquals(ConnAckMessage.BAD_USERNAME_OR_PASSWORD, evilSession.getReturnCode()); assertEqualsConnAck(BAD_USERNAME_OR_PASSWORD, evilSession.readOutbound());
//the good client remains connected //the good client remains connected
assertFalse(m_session.isClosed()); assertTrue(m_session.isOpen());
assertTrue(evilSession.isClosed()); assertFalse(evilSession.isOpen());
} }
@@ -239,8 +243,8 @@ public class ProtocolProcessor_CONNECT_Test {
connMsg.setProtocolVersion(VERSION_3_1_1); connMsg.setProtocolVersion(VERSION_3_1_1);
connMsg.setClientID("CliID"); connMsg.setClientID("CliID");
connMsg.setCleanSession(false); connMsg.setCleanSession(false);
m_session.setAttribute(NettyChannel.ATTR_KEY_CLIENTID, "CliID"); m_session.attr(NettyChannel.ATTR_KEY_CLIENTID).set("CliID");
m_session.setAttribute(NettyChannel.ATTR_KEY_CLEANSESSION, false); m_session.attr(NettyChannel.ATTR_KEY_CLIENTID).set(false);
//Connect a first time //Connect a first time
m_processor.processConnect(m_session, connMsg); m_processor.processConnect(m_session, connMsg);
@@ -248,15 +252,11 @@ public class ProtocolProcessor_CONNECT_Test {
m_processor.processDisconnect(m_session); m_processor.processDisconnect(m_session);
//Exercise, reconnect //Exercise, reconnect
MockReceiverChannel firstReceiverSession = new MockReceiverChannel(); EmbeddedChannel firstReceiverSession = new EmbeddedChannel();
m_processor.processConnect(firstReceiverSession, connMsg); m_processor.processConnect(firstReceiverSession, connMsg);
//Verify //Verify
AbstractMessage recvMsg = firstReceiverSession.getMessage(); assertEqualsConnAck(CONNECTION_ACCEPTED, firstReceiverSession.readOutbound());
assertTrue(recvMsg instanceof ConnAckMessage);
ConnAckMessage connAckMsg = (ConnAckMessage) recvMsg;
assertTrue(connAckMsg.isSessionPresent());
assertEquals(ConnAckMessage.CONNECTION_ACCEPTED, connAckMsg.getReturnCode());
} }
@@ -268,24 +268,27 @@ public class ProtocolProcessor_CONNECT_Test {
connMsg.setClientID("CliID"); connMsg.setClientID("CliID");
connMsg.setCleanSession(false); connMsg.setCleanSession(false);
m_processor.processConnect(m_session, connMsg); m_processor.processConnect(m_session, connMsg);
assertEquals(ConnAckMessage.CONNECTION_ACCEPTED, m_session.getReturnCode()); assertEqualsConnAck(CONNECTION_ACCEPTED, m_session.readOutbound());
//subscribe //subscribe
SubscribeMessage subscribeMsg = new SubscribeMessage(); SubscribeMessage subscribeMsg = new SubscribeMessage();
subscribeMsg.addSubscription(new SubscribeMessage.Couple((byte) AbstractMessage.QOSType.MOST_ONE.ordinal(), ProtocolProcessorTest.FAKE_TOPIC)); subscribeMsg.addSubscription(new SubscribeMessage.Couple((byte) AbstractMessage.QOSType.MOST_ONE.ordinal(), ProtocolProcessorTest.FAKE_TOPIC));
m_session.setAttribute(NettyChannel.ATTR_KEY_CLIENTID, "CliID"); m_session.attr(NettyChannel.ATTR_KEY_CLIENTID).set("CliID");
m_session.setAttribute(NettyChannel.ATTR_KEY_CLEANSESSION, false); m_session.attr(NettyChannel.ATTR_KEY_CLEANSESSION).set(false);
m_processor.processSubscribe(m_session, subscribeMsg); m_processor.processSubscribe(m_session, subscribeMsg);
Subscription expectedSubscription = new Subscription("CliID", ProtocolProcessorTest.FAKE_TOPIC, Subscription expectedSubscription = new Subscription("CliID", ProtocolProcessorTest.FAKE_TOPIC,
AbstractMessage.QOSType.MOST_ONE); AbstractMessage.QOSType.MOST_ONE);
assertTrue(subscriptions.contains(expectedSubscription)); assertTrue(subscriptions.contains(expectedSubscription));
assertEqualsSubAck(m_session.readOutbound());
//disconnect //disconnect
m_processor.processDisconnect(m_session); 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, connMsg); m_processor.processConnect(m_session, connMsg);
assertEquals(ConnAckMessage.CONNECTION_ACCEPTED, m_session.getReturnCode()); assertEqualsConnAck(CONNECTION_ACCEPTED, m_session.readOutbound());
//verify that the first subscription is still preserved //verify that the first subscription is still preserved
assertTrue(subscriptions.contains(expectedSubscription)); assertTrue(subscriptions.contains(expectedSubscription));