diff --git a/application/build.gradle b/application/build.gradle index 4c8d02dd..c4c1fcd2 100644 --- a/application/build.gradle +++ b/application/build.gradle @@ -12,6 +12,7 @@ dependencies { implementation libs.springboot.starter.log4j2 testImplementation projects.testSupport + testImplementation testFixtures(projects.network) } tasks.withType(GroovyCompile).configureEach { diff --git a/application/src/main/java/javasabr/mqtt/broker/application/config/MqttBrokerSpringConfig.java b/application/src/main/java/javasabr/mqtt/broker/application/config/MqttBrokerSpringConfig.java index a087aa1c..ac31d115 100644 --- a/application/src/main/java/javasabr/mqtt/broker/application/config/MqttBrokerSpringConfig.java +++ b/application/src/main/java/javasabr/mqtt/broker/application/config/MqttBrokerSpringConfig.java @@ -16,7 +16,6 @@ import javasabr.mqtt.service.MessageOutFactoryService; import javasabr.mqtt.service.PublishDeliveringService; import javasabr.mqtt.service.PublishReceivingService; -import javasabr.mqtt.service.SessionService; import javasabr.mqtt.service.SubscriptionService; import javasabr.mqtt.service.handler.client.ExternalMqttClientReleaseHandler; import javasabr.mqtt.service.impl.DefaultConnectionService; @@ -27,7 +26,6 @@ import javasabr.mqtt.service.impl.ExternalMqttClientFactory; import javasabr.mqtt.service.impl.FileCredentialsSource; import javasabr.mqtt.service.impl.InMemoryClientIdRegistry; -import javasabr.mqtt.service.impl.InMemorySessionService; import javasabr.mqtt.service.impl.SimpleAuthenticationService; import javasabr.mqtt.service.impl.SimpleSubscriptionService; import javasabr.mqtt.service.message.handler.MqttInMessageHandler; @@ -51,6 +49,8 @@ import javasabr.mqtt.service.publish.handler.impl.Qos1MqttPublishOutMessageHandler; import javasabr.mqtt.service.publish.handler.impl.Qos2MqttPublishInMessageHandler; import javasabr.mqtt.service.publish.handler.impl.Qos2MqttPublishOutMessageHandler; +import javasabr.mqtt.service.session.MqttSessionService; +import javasabr.mqtt.service.session.impl.InMemoryMqttSessionService; import javasabr.rlib.network.NetworkFactory; import javasabr.rlib.network.ServerNetworkConfig; import javasabr.rlib.network.server.ServerNetwork; @@ -76,9 +76,9 @@ ClientIdRegistry clientIdRegistry(Environment env) { } @Bean - SessionService mqttSessionService( + MqttSessionService mqttSessionService( @Value("${sessions.clean.thread.interval:60000}") int cleanInterval) { - return new InMemorySessionService(cleanInterval); + return new InMemoryMqttSessionService(cleanInterval); } @Bean @@ -119,7 +119,7 @@ MessageOutFactoryService mqttMessageOutFactoryService( MqttInMessageHandler connectInMqttInMessageHandler( ClientIdRegistry clientIdRegistry, AuthenticationService authenticationService, - SessionService sessionService, + MqttSessionService sessionService, SubscriptionService subscriptionService, MessageOutFactoryService messageOutFactoryService) { return new ConnectInMqttInMessageHandler( @@ -244,7 +244,7 @@ PublishReceivingService publishReceivingService( @Bean MqttClientReleaseHandler externalMqttClientReleaseHandler( ClientIdRegistry clientIdRegistry, - SessionService sessionService, + MqttSessionService sessionService, SubscriptionService subscriptionService) { return new ExternalMqttClientReleaseHandler(clientIdRegistry, sessionService, subscriptionService); } diff --git a/application/src/test/groovy/javasabr/mqtt/application/integration/InternalConnectionTest.groovy b/application/src/test/groovy/javasabr/mqtt/application/integration/InternalConnectionTest.groovy deleted file mode 100644 index 62ca98f7..00000000 --- a/application/src/test/groovy/javasabr/mqtt/application/integration/InternalConnectionTest.groovy +++ /dev/null @@ -1,39 +0,0 @@ -package javasabr.mqtt.application.integration - -import com.hivemq.client.mqtt.mqtt3.message.connect.connack.Mqtt3ConnAckReturnCode -import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAckReasonCode -import javasabr.mqtt.model.MqttProperties - -class InternalConnectionTest extends IntegrationSpecification { - - def "client should connect to broker without user and pass using mqtt 3.1.1"() { - given: - def client = buildInternalMqtt311Client() - when: - def result = client.connect().join() - then: - result.returnCode == Mqtt3ConnAckReturnCode.SUCCESS - !result.sessionPresent - cleanup: - client.disconnect().join() - } - - def "client should connect to broker without user and pass using mqtt 5"() { - given: - def client = buildInternalMqtt5Client() - when: - def result = client.connect().join() - then: - result.reasonCode == Mqtt5ConnAckReasonCode.SUCCESS - result.sessionExpiryInterval.present - result.sessionExpiryInterval.getAsLong() == MqttProperties.SESSION_EXPIRY_INTERVAL_DEFAULT - result.serverKeepAlive.present - result.serverKeepAlive.getAsInt() == MqttProperties.SERVER_KEEP_ALIVE_DISABLED - !result.serverReference.present - !result.responseInformation.present - !result.assignedClientIdentifier.present - !result.sessionPresent - cleanup: - client.disconnect().join() - } -} diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/in/BaseInPacketTest.groovy b/application/src/test/groovy/javasabr/mqtt/application/network/in/BaseInPacketTest.groovy deleted file mode 100644 index 6ef65ea8..00000000 --- a/application/src/test/groovy/javasabr/mqtt/application/network/in/BaseInPacketTest.groovy +++ /dev/null @@ -1,6 +0,0 @@ -package javasabr.mqtt.application.network.in - -import javasabr.mqtt.application.network.NetworkUnitSpecification - -class BaseInPacketTest extends NetworkUnitSpecification { -} diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/out/BaseOutPacketTest.groovy b/application/src/test/groovy/javasabr/mqtt/application/network/out/BaseOutPacketTest.groovy deleted file mode 100644 index 9885c71d..00000000 --- a/application/src/test/groovy/javasabr/mqtt/application/network/out/BaseOutPacketTest.groovy +++ /dev/null @@ -1,7 +0,0 @@ -package javasabr.mqtt.application.network.out - -import javasabr.mqtt.application.network.NetworkUnitSpecification - -class BaseOutPacketTest extends NetworkUnitSpecification { - -} diff --git a/application/src/test/groovy/javasabr/mqtt/application/integration/ConnectSubscribePublishTest.groovy b/application/src/test/groovy/javasabr/mqtt/broker/application/ConnectSubscribePublishTest.groovy similarity index 99% rename from application/src/test/groovy/javasabr/mqtt/application/integration/ConnectSubscribePublishTest.groovy rename to application/src/test/groovy/javasabr/mqtt/broker/application/ConnectSubscribePublishTest.groovy index 4cc64905..d38112f9 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/integration/ConnectSubscribePublishTest.groovy +++ b/application/src/test/groovy/javasabr/mqtt/broker/application/ConnectSubscribePublishTest.groovy @@ -1,4 +1,4 @@ -package javasabr.mqtt.application.integration +package javasabr.mqtt.broker.application import com.hivemq.client.mqtt.datatypes.MqttQos import com.hivemq.client.mqtt.mqtt3.Mqtt3AsyncClient diff --git a/application/src/test/groovy/javasabr/mqtt/application/integration/ExternalConnectionTest.groovy b/application/src/test/groovy/javasabr/mqtt/broker/application/ExternalConnectionTest.groovy similarity index 95% rename from application/src/test/groovy/javasabr/mqtt/application/integration/ExternalConnectionTest.groovy rename to application/src/test/groovy/javasabr/mqtt/broker/application/ExternalConnectionTest.groovy index f502dfa4..47ad60af 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/integration/ExternalConnectionTest.groovy +++ b/application/src/test/groovy/javasabr/mqtt/broker/application/ExternalConnectionTest.groovy @@ -1,4 +1,4 @@ -package javasabr.mqtt.application.integration +package javasabr.mqtt.broker.application import com.hivemq.client.mqtt.mqtt3.exceptions.Mqtt3ConnAckException import com.hivemq.client.mqtt.mqtt3.message.connect.connack.Mqtt3ConnAckReturnCode @@ -7,8 +7,8 @@ import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAckReasonCo import javasabr.mqtt.model.MqttProperties import javasabr.mqtt.model.QoS import javasabr.mqtt.model.reason.code.ConnectAckReasonCode -import javasabr.mqtt.network.packet.in.ConnectAckInPacket -import javasabr.mqtt.network.packet.out.Connect311OutPacket +import javasabr.mqtt.network.message.in.ConnectAckMqttInMessage +import javasabr.mqtt.network.message.out.ConnectMqtt311OutMessage import javasabr.rlib.common.util.ArrayUtils import spock.lang.Ignore @@ -148,7 +148,7 @@ class ExternalConnectionTest extends IntegrationSpecification { when: client.connect() - client.send(new Connect311OutPacket( + client.send(new ConnectMqtt311OutMessage( "", "", clientId, @@ -160,7 +160,7 @@ class ExternalConnectionTest extends IntegrationSpecification { false )) - def connectAck = client.readNext() as ConnectAckInPacket + def connectAck = client.readNext() as ConnectAckMqttInMessage then: connectAck.reasonCode == ConnectAckReasonCode.BAD_USER_NAME_OR_PASSWORD diff --git a/application/src/test/groovy/javasabr/mqtt/application/integration/IntegrationSpecification.groovy b/application/src/test/groovy/javasabr/mqtt/broker/application/IntegrationSpecification.groovy similarity index 61% rename from application/src/test/groovy/javasabr/mqtt/application/integration/IntegrationSpecification.groovy rename to application/src/test/groovy/javasabr/mqtt/broker/application/IntegrationSpecification.groovy index 0fc5425c..366e9321 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/integration/IntegrationSpecification.groovy +++ b/application/src/test/groovy/javasabr/mqtt/broker/application/IntegrationSpecification.groovy @@ -1,20 +1,22 @@ -package javasabr.mqtt.application.integration +package javasabr.mqtt.broker.application import com.hivemq.client.mqtt.MqttClient import com.hivemq.client.mqtt.mqtt3.Mqtt3AsyncClient import com.hivemq.client.mqtt.mqtt5.Mqtt5AsyncClient -import javasabr.mqtt.application.integration.config.MqttBrokerTestConfig -import javasabr.mqtt.application.mock.MqttMockClient +import javasabr.mqtt.broker.application.config.MqttBrokerTestConfig +import javasabr.mqtt.model.MqttClientConnectionConfig import javasabr.mqtt.model.MqttProperties import javasabr.mqtt.model.MqttServerConnectionConfig import javasabr.mqtt.model.MqttVersion import javasabr.mqtt.network.MqttConnection +import javasabr.mqtt.network.MqttMockClient import org.springframework.beans.factory.annotation.Autowired import org.springframework.test.context.junit.jupiter.SpringJUnitConfig import spock.lang.Specification import java.nio.charset.StandardCharsets import java.util.concurrent.atomic.AtomicInteger +import java.util.concurrent.atomic.AtomicReference import static javasabr.mqtt.network.MqttClient.UnsafeMqttClient @@ -32,9 +34,6 @@ class IntegrationSpecification extends Specification { @Autowired InetSocketAddress externalNetworkAddress - @Autowired - InetSocketAddress internalNetworkAddress - @Autowired MqttServerConnectionConfig externalConnectionConfig @@ -42,18 +41,10 @@ class IntegrationSpecification extends Specification { return buildMqtt311Client(generateClientId(), externalNetworkAddress) } - def buildInternalMqtt311Client() { - return buildMqtt311Client(generateClientId(), internalNetworkAddress) - } - def buildExternalMqtt5Client() { return buildMqtt5Client(generateClientId(), externalNetworkAddress) } - def buildInternalMqtt5Client() { - return buildMqtt5Client(generateClientId(), internalNetworkAddress) - } - def buildExternalMqtt311Client(String clientId) { return MqttClient.builder() .identifier(clientId) @@ -71,7 +62,7 @@ class IntegrationSpecification extends Specification { .serverPort(address.getPort()) .useMqttVersion3() .addDisconnectedListener { - println "[${clientId}|mqtt311] disconnected:[$it.cause]" + println "[${clientId}|mqtt311] disconnected:[${it.cause.message}]" } .build() .toAsync() @@ -94,7 +85,7 @@ class IntegrationSpecification extends Specification { .serverPort(address.getPort()) .useMqttVersion5() .addDisconnectedListener { - println "[${clientId}|mqtt5] disconnected:[$it.cause]" + println "[${clientId}|mqtt5] disconnected:[${it.cause.message}]" } .build() .toAsync() @@ -144,38 +135,65 @@ class IntegrationSpecification extends Specification { ) } - def mqtt5MockedConnection(MqttServerConnectionConfig deviceConnectionConfig) { - - return Stub(MqttConnection) { + def mqtt5MockedConnection(MqttServerConnectionConfig serverConnConfig) { + MqttClientConnectionConfig clientConnConfig = new MqttClientConnectionConfig( + serverConnConfig.maxQos(), + MqttVersion.MQTT_5, + MqttProperties.SESSION_EXPIRY_INTERVAL_DISABLED, + serverConnConfig.receiveMaxPublishes(), + serverConnConfig.maxPacketSize(), + serverConnConfig.topicAliasMaxValue(), + MqttProperties.SERVER_KEEP_ALIVE_DEFAULT, + false, + false, + serverConnConfig.sessionsEnabled(), + serverConnConfig.retainAvailable(), + serverConnConfig.wildcardSubscriptionAvailable(), + serverConnConfig.subscriptionIdAvailable(), + serverConnConfig.sharedSubscriptionAvailable()) + def connectionRef = new AtomicReference() + def connection = Stub(MqttConnection) { isSupported(MqttVersion.MQTT_5) >> true isSupported(MqttVersion.MQTT_3_1_1) >> true - serverConnectionConfig() >> deviceConnectionConfig + serverConnectionConfig() >> serverConnConfig client() >> Stub(UnsafeMqttClient) { - connectionConfig() >> deviceConnectionConfig - sessionExpiryInterval() >> MqttProperties.SESSION_EXPIRY_INTERVAL_DISABLED - receiveMaxPublishes() >> deviceConnectionConfig.receiveMaxPublishes() - maxPacketSize() >> deviceConnectionConfig.maxPacketSize() - clientId() >> IntegrationSpecification.clientId - keepAlive() >> MqttProperties.SERVER_KEEP_ALIVE_DEFAULT - topicAliasMaxValue() >> deviceConnectionConfig.topicAliasMaxValue() + connectionConfig() >> clientConnConfig + connection() >> connectionRef.get() + clientId() >> clientId } } - } - - def mqtt311MockedConnection(MqttServerConnectionConfig deviceConnectionConfig) { - return Stub(MqttConnection) { + connectionRef.set(connection) + return connection + } + + def mqtt311MockedConnection(MqttServerConnectionConfig serverConnConfig) { + MqttClientConnectionConfig clientConnConfig = new MqttClientConnectionConfig( + serverConnConfig.maxQos(), + MqttVersion.MQTT_3_1_1, + MqttProperties.SESSION_EXPIRY_INTERVAL_DISABLED, + serverConnConfig.receiveMaxPublishes(), + serverConnConfig.maxPacketSize(), + serverConnConfig.topicAliasMaxValue(), + MqttProperties.SERVER_KEEP_ALIVE_DEFAULT, + false, + false, + serverConnConfig.sessionsEnabled(), + serverConnConfig.retainAvailable(), + serverConnConfig.wildcardSubscriptionAvailable(), + serverConnConfig.subscriptionIdAvailable(), + serverConnConfig.sharedSubscriptionAvailable()) + def connectionRef = new AtomicReference() + def connection = Stub(MqttConnection) { isSupported(MqttVersion.MQTT_5) >> false isSupported(MqttVersion.MQTT_3_1_1) >> true - serverConnectionConfig() >> deviceConnectionConfig + serverConnectionConfig() >> serverConnConfig client() >> Stub(UnsafeMqttClient) { - connectionConfig() >> deviceConnectionConfig - sessionExpiryInterval() >> MqttProperties.SESSION_EXPIRY_INTERVAL_DISABLED - receiveMaxPublishes() >> deviceConnectionConfig.receiveMaxPublishes() - maxPacketSize() >> deviceConnectionConfig.maxPacketSize() - clientId() >> IntegrationSpecification.clientId - keepAlive() >> MqttProperties.SERVER_KEEP_ALIVE_DEFAULT - topicAliasMaxValue() >> deviceConnectionConfig.topicAliasMaxValue() + connectionConfig() >> clientConnConfig + connection() >> connectionRef.get() + clientId() >> clientId } } + connectionRef.set(connection) + return connection } } diff --git a/application/src/test/groovy/javasabr/mqtt/application/integration/PublishRetryTest.groovy b/application/src/test/groovy/javasabr/mqtt/broker/application/PublishRetryTest.groovy similarity index 64% rename from application/src/test/groovy/javasabr/mqtt/application/integration/PublishRetryTest.groovy rename to application/src/test/groovy/javasabr/mqtt/broker/application/PublishRetryTest.groovy index e2f5486d..fc291d25 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/integration/PublishRetryTest.groovy +++ b/application/src/test/groovy/javasabr/mqtt/broker/application/PublishRetryTest.groovy @@ -1,4 +1,4 @@ -package javasabr.mqtt.application.integration +package javasabr.mqtt.broker.application import com.hivemq.client.mqtt.datatypes.MqttQos import javasabr.mqtt.model.QoS @@ -7,19 +7,19 @@ import javasabr.mqtt.model.reason.code.PublishCompletedReasonCode import javasabr.mqtt.model.reason.code.PublishReceivedReasonCode import javasabr.mqtt.model.reason.code.SubscribeAckReasonCode import javasabr.mqtt.model.subscriber.SubscribeTopicFilter -import javasabr.mqtt.network.packet.in.ConnectAckInPacket -import javasabr.mqtt.network.packet.in.PublishInPacket -import javasabr.mqtt.network.packet.in.PublishReleaseInPacket -import javasabr.mqtt.network.packet.in.SubscribeAckInPacket -import javasabr.mqtt.network.packet.out.* -import javasabr.mqtt.service.SessionService +import javasabr.mqtt.network.message.in.ConnectAckMqttInMessage +import javasabr.mqtt.network.message.in.PublishMqttInMessage +import javasabr.mqtt.network.message.in.PublishReleaseMqttInMessage +import javasabr.mqtt.network.message.in.SubscribeAckMqttInMessage +import javasabr.mqtt.network.message.out.* +import javasabr.mqtt.service.session.MqttSessionService import javasabr.rlib.collections.array.Array import org.springframework.beans.factory.annotation.Autowired class PublishRetryTest extends IntegrationSpecification { @Autowired - SessionService mqttSessionService + MqttSessionService mqttSessionService def "mqtt 3.1.1 client should be generate session with one pending QoS 1 packet"() { given: @@ -29,16 +29,16 @@ class PublishRetryTest extends IntegrationSpecification { when: publisher.connect().join() subscriber.connect() - subscriber.send(new Connect311OutPacket(subscriberId, keepAlive)) - def connectAck = subscriber.readNext() as ConnectAckInPacket + subscriber.send(new ConnectMqtt311OutMessage(subscriberId, keepAlive)) + def connectAck = subscriber.readNext() as ConnectAckMqttInMessage then: connectAck.reasonCode == ConnectAckReasonCode.SUCCESS when: - subscriber.send(new Subscribe311OutPacket( + subscriber.send(new SubscribeMqtt311OutMessage( Array.of(new SubscribeTopicFilter("test/retry/$subscriberId", QoS.AT_LEAST_ONCE)), 1 )) - def subscribeAck = subscriber.readNext() as SubscribeAckInPacket + def subscribeAck = subscriber.readNext() as SubscribeAckMqttInMessage then: subscribeAck.reasonCodes.stream() .allMatch({ it == SubscribeAckReasonCode.GRANTED_QOS_1 }) @@ -49,20 +49,20 @@ class PublishRetryTest extends IntegrationSpecification { .payload(publishPayload) .send() .join() - def receivedPublish = subscriber.readNext() as PublishInPacket + def receivedPublish = subscriber.readNext() as PublishMqttInMessage then: receivedPublish.payload == publishPayload when: subscriber.disconnect() Thread.sleep(1_000) subscriber.connect() - subscriber.send(new Connect311OutPacket(subscriberId, keepAlive)) - connectAck = subscriber.readNext() as ConnectAckInPacket - def receivedDupPublish = subscriber.readNext() as PublishInPacket + subscriber.send(new ConnectMqtt311OutMessage(subscriberId, keepAlive)) + connectAck = subscriber.readNext() as ConnectAckMqttInMessage + def receivedDupPublish = subscriber.readNext() as PublishMqttInMessage then: connectAck.reasonCode == ConnectAckReasonCode.SUCCESS receivedDupPublish.duplicate - receivedDupPublish.packetId == receivedPublish.packetId + receivedDupPublish.messageId == receivedPublish.messageId receivedDupPublish.payload == publishPayload cleanup: subscriber.close() @@ -77,16 +77,16 @@ class PublishRetryTest extends IntegrationSpecification { when: publisher.connect().join() subscriber.connect() - subscriber.send(new Connect5OutPacket(subscriberId, keepAlive)) - def connectAck = subscriber.readNext() as ConnectAckInPacket + subscriber.send(new ConnectMqtt5OutMessage(subscriberId, keepAlive)) + def connectAck = subscriber.readNext() as ConnectAckMqttInMessage then: connectAck.reasonCode == ConnectAckReasonCode.SUCCESS when: - subscriber.send(new Subscribe5OutPacket( + subscriber.send(new SubscribeMqtt5OutMessage( Array.of(new SubscribeTopicFilter("test/retry/$subscriberId", QoS.AT_LEAST_ONCE)), 1 )) - def subscribeAck = subscriber.readNext() as SubscribeAckInPacket + def subscribeAck = subscriber.readNext() as SubscribeAckMqttInMessage then: subscribeAck.reasonCodes.stream() .allMatch({ it == SubscribeAckReasonCode.GRANTED_QOS_1 }) @@ -98,19 +98,19 @@ class PublishRetryTest extends IntegrationSpecification { .send() .join() - def receivedPublish = subscriber.readNext() as PublishInPacket + def receivedPublish = subscriber.readNext() as PublishMqttInMessage then: receivedPublish.payload == publishPayload when: subscriber.disconnect() subscriber.connect() - subscriber.send(new Connect5OutPacket(subscriberId, keepAlive)) - connectAck = subscriber.readNext() as ConnectAckInPacket - def receivedDupPublish = subscriber.readNext() as PublishInPacket + subscriber.send(new ConnectMqtt5OutMessage(subscriberId, keepAlive)) + connectAck = subscriber.readNext() as ConnectAckMqttInMessage + def receivedDupPublish = subscriber.readNext() as PublishMqttInMessage then: connectAck.reasonCode == ConnectAckReasonCode.SUCCESS receivedDupPublish.duplicate - receivedDupPublish.packetId == receivedPublish.packetId + receivedDupPublish.messageId == receivedPublish.messageId receivedDupPublish.payload == publishPayload cleanup: subscriber.close() @@ -125,16 +125,16 @@ class PublishRetryTest extends IntegrationSpecification { when: publisher.connect().join() subscriber.connect() - subscriber.send(new Connect311OutPacket(subscriberId, keepAlive)) - def connectAck = subscriber.readNext() as ConnectAckInPacket + subscriber.send(new ConnectMqtt311OutMessage(subscriberId, keepAlive)) + def connectAck = subscriber.readNext() as ConnectAckMqttInMessage then: connectAck.reasonCode == ConnectAckReasonCode.SUCCESS when: - subscriber.send(new Subscribe311OutPacket( + subscriber.send(new SubscribeMqtt311OutMessage( Array.of(new SubscribeTopicFilter("test/retry/$subscriberId", QoS.EXACTLY_ONCE)), 1 )) - def subscribeAck = subscriber.readNext() as SubscribeAckInPacket + def subscribeAck = subscriber.readNext() as SubscribeAckMqttInMessage then: subscribeAck.reasonCodes.stream() .allMatch({ it == SubscribeAckReasonCode.GRANTED_QOS_2 }) @@ -146,35 +146,35 @@ class PublishRetryTest extends IntegrationSpecification { .send() .join() - def receivedPublish = subscriber.readNext() as PublishInPacket + def receivedPublish = subscriber.readNext() as PublishMqttInMessage then: receivedPublish.payload == publishPayload when: subscriber.disconnect() subscriber.connect() - subscriber.send(new Connect311OutPacket(subscriberId, keepAlive)) - connectAck = subscriber.readNext() as ConnectAckInPacket - def receivedDupPublish = subscriber.readNext() as PublishInPacket + subscriber.send(new ConnectMqtt311OutMessage(subscriberId, keepAlive)) + connectAck = subscriber.readNext() as ConnectAckMqttInMessage + def receivedDupPublish = subscriber.readNext() as PublishMqttInMessage then: connectAck.reasonCode == ConnectAckReasonCode.SUCCESS receivedDupPublish.duplicate - receivedDupPublish.packetId == receivedPublish.packetId + receivedDupPublish.messageId == receivedPublish.messageId receivedDupPublish.payload == publishPayload when: subscriber.disconnect() subscriber.connect() - subscriber.send(new Connect311OutPacket(subscriberId, keepAlive)) - connectAck = subscriber.readNext() as ConnectAckInPacket - receivedDupPublish = subscriber.readNext() as PublishInPacket - subscriber.send(new PublishReceived311OutPacket(receivedDupPublish.getPacketId())) - def releaseAck = subscriber.readNext() as PublishReleaseInPacket - subscriber.send(new PublishComplete311OutPacket(receivedDupPublish.getPacketId())) + subscriber.send(new ConnectMqtt311OutMessage(subscriberId, keepAlive)) + connectAck = subscriber.readNext() as ConnectAckMqttInMessage + receivedDupPublish = subscriber.readNext() as PublishMqttInMessage + subscriber.send(new PublishReceivedMqtt311OutMessage(receivedDupPublish.messageId())) + def releaseAck = subscriber.readNext() as PublishReleaseMqttInMessage + subscriber.send(new PublishCompleteMqtt311OutMessage(receivedDupPublish.messageId())) then: connectAck.reasonCode == ConnectAckReasonCode.SUCCESS receivedDupPublish.duplicate - receivedDupPublish.packetId == receivedPublish.packetId + receivedDupPublish.messageId == receivedPublish.messageId receivedDupPublish.payload == publishPayload - releaseAck.packetId == receivedPublish.packetId + releaseAck.messageId == receivedPublish.messageId cleanup: subscriber.close() publisher.disconnect().join() @@ -188,16 +188,16 @@ class PublishRetryTest extends IntegrationSpecification { when: publisher.connect().join() subscriber.connect() - subscriber.send(new Connect5OutPacket(subscriberId, keepAlive)) - def connectAck = subscriber.readNext() as ConnectAckInPacket + subscriber.send(new ConnectMqtt5OutMessage(subscriberId, keepAlive)) + def connectAck = subscriber.readNext() as ConnectAckMqttInMessage then: connectAck.reasonCode == ConnectAckReasonCode.SUCCESS when: - subscriber.send(new Subscribe5OutPacket( + subscriber.send(new SubscribeMqtt5OutMessage( Array.of(new SubscribeTopicFilter("test/retry/$subscriberId", QoS.EXACTLY_ONCE)), 1 )) - def subscribeAck = subscriber.readNext() as SubscribeAckInPacket + def subscribeAck = subscriber.readNext() as SubscribeAckMqttInMessage then: subscribeAck.reasonCodes.stream() .allMatch({ it == SubscribeAckReasonCode.GRANTED_QOS_2 }) @@ -209,42 +209,42 @@ class PublishRetryTest extends IntegrationSpecification { .send() .join() - def receivedPublish = subscriber.readNext() as PublishInPacket + def receivedPublish = subscriber.readNext() as PublishMqttInMessage then: receivedPublish.payload == publishPayload when: subscriber.disconnect() subscriber.connect() - subscriber.send(new Connect5OutPacket(subscriberId, keepAlive)) - connectAck = subscriber.readNext() as ConnectAckInPacket - def receivedDupPublish = subscriber.readNext() as PublishInPacket + subscriber.send(new ConnectMqtt5OutMessage(subscriberId, keepAlive)) + connectAck = subscriber.readNext() as ConnectAckMqttInMessage + def receivedDupPublish = subscriber.readNext() as PublishMqttInMessage then: connectAck.reasonCode == ConnectAckReasonCode.SUCCESS receivedDupPublish.duplicate - receivedDupPublish.packetId == receivedPublish.packetId + receivedDupPublish.messageId == receivedPublish.messageId receivedDupPublish.payload == publishPayload when: subscriber.disconnect() subscriber.connect() - subscriber.send(new Connect5OutPacket(subscriberId, keepAlive)) - connectAck = subscriber.readNext() as ConnectAckInPacket - receivedDupPublish = subscriber.readNext() as PublishInPacket - subscriber.send(new PublishReceived5OutPacket( - receivedDupPublish.getPacketId(), + subscriber.send(new ConnectMqtt5OutMessage(subscriberId, keepAlive)) + connectAck = subscriber.readNext() as ConnectAckMqttInMessage + receivedDupPublish = subscriber.readNext() as PublishMqttInMessage + subscriber.send(new PublishReceivedMqtt5OutMessage( + receivedDupPublish.messageId(), PublishReceivedReasonCode.SUCCESS )) - def releaseAck = subscriber.readNext() as PublishReleaseInPacket - subscriber.send(new PublishComplete5OutPacket( - receivedDupPublish.getPacketId(), + def releaseAck = subscriber.readNext() as PublishReleaseMqttInMessage + subscriber.send(new PublishCompleteMqtt5OutMessage( + receivedDupPublish.messageId(), PublishCompletedReasonCode.SUCCESS )) then: connectAck.reasonCode == ConnectAckReasonCode.SUCCESS receivedDupPublish.duplicate - receivedDupPublish.packetId == receivedPublish.packetId + receivedDupPublish.messageId == receivedPublish.messageId receivedDupPublish.payload == publishPayload - releaseAck.packetId == receivedPublish.packetId + releaseAck.messageId == receivedPublish.messageId cleanup: subscriber.close() publisher.disconnect().join() diff --git a/application/src/test/groovy/javasabr/mqtt/application/integration/config/MqttBrokerTestConfig.groovy b/application/src/test/groovy/javasabr/mqtt/broker/application/config/MqttBrokerTestConfig.groovy similarity index 92% rename from application/src/test/groovy/javasabr/mqtt/application/integration/config/MqttBrokerTestConfig.groovy rename to application/src/test/groovy/javasabr/mqtt/broker/application/config/MqttBrokerTestConfig.groovy index 69cee195..35b6f927 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/integration/config/MqttBrokerTestConfig.groovy +++ b/application/src/test/groovy/javasabr/mqtt/broker/application/config/MqttBrokerTestConfig.groovy @@ -1,6 +1,5 @@ -package javasabr.mqtt.application.integration.config +package javasabr.mqtt.broker.application.config -import javasabr.mqtt.broker.application.config.MqttBrokerSpringConfig import javasabr.mqtt.network.MqttConnection import javasabr.mqtt.service.ConnectionService import javasabr.rlib.network.server.ServerNetwork diff --git a/application/src/test/groovy/javasabr/mqtt/application/integration/service/ClientIdRegistryTest.groovy b/application/src/test/groovy/javasabr/mqtt/broker/application/service/ClientIdRegistryTest.groovy similarity index 96% rename from application/src/test/groovy/javasabr/mqtt/application/integration/service/ClientIdRegistryTest.groovy rename to application/src/test/groovy/javasabr/mqtt/broker/application/service/ClientIdRegistryTest.groovy index 94922925..210e3fa5 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/integration/service/ClientIdRegistryTest.groovy +++ b/application/src/test/groovy/javasabr/mqtt/broker/application/service/ClientIdRegistryTest.groovy @@ -1,7 +1,7 @@ -package javasabr.mqtt.application.integration.service +package javasabr.mqtt.broker.application.service import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAckReasonCode -import javasabr.mqtt.application.integration.IntegrationSpecification +import javasabr.mqtt.broker.application.IntegrationSpecification import javasabr.mqtt.service.ClientIdRegistry import javasabr.rlib.common.util.StringUtils import org.springframework.beans.factory.annotation.Autowired diff --git a/application/src/test/groovy/javasabr/mqtt/application/integration/service/DisabledFeaturesSubscribtionServiceTest.groovy b/application/src/test/groovy/javasabr/mqtt/broker/application/service/DisabledFeaturesSubscribtionServiceTest.groovy similarity index 93% rename from application/src/test/groovy/javasabr/mqtt/application/integration/service/DisabledFeaturesSubscribtionServiceTest.groovy rename to application/src/test/groovy/javasabr/mqtt/broker/application/service/DisabledFeaturesSubscribtionServiceTest.groovy index 8fd50bae..4b4ba715 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/integration/service/DisabledFeaturesSubscribtionServiceTest.groovy +++ b/application/src/test/groovy/javasabr/mqtt/broker/application/service/DisabledFeaturesSubscribtionServiceTest.groovy @@ -1,9 +1,9 @@ -package javasabr.mqtt.application.integration.service +package javasabr.mqtt.broker.application.service import com.hivemq.client.mqtt.MqttClientState import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5SubAckException import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAckReasonCode -import javasabr.mqtt.application.integration.IntegrationSpecification +import javasabr.mqtt.broker.application.IntegrationSpecification import org.springframework.test.context.TestPropertySource import spock.lang.Unroll diff --git a/application/src/test/groovy/javasabr/mqtt/application/integration/service/SessionServiceTest.groovy b/application/src/test/groovy/javasabr/mqtt/broker/application/service/MqttSessionServiceTest.groovy similarity index 83% rename from application/src/test/groovy/javasabr/mqtt/application/integration/service/SessionServiceTest.groovy rename to application/src/test/groovy/javasabr/mqtt/broker/application/service/MqttSessionServiceTest.groovy index 831bd6dd..cf362778 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/integration/service/SessionServiceTest.groovy +++ b/application/src/test/groovy/javasabr/mqtt/broker/application/service/MqttSessionServiceTest.groovy @@ -1,18 +1,18 @@ -package javasabr.mqtt.application.integration.service +package javasabr.mqtt.broker.application.service import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAckReasonCode -import javasabr.mqtt.application.integration.IntegrationSpecification +import javasabr.mqtt.broker.application.IntegrationSpecification import javasabr.mqtt.service.ClientIdRegistry -import javasabr.mqtt.service.SessionService +import javasabr.mqtt.service.session.MqttSessionService import org.springframework.beans.factory.annotation.Autowired -class SessionServiceTest extends IntegrationSpecification { +class MqttSessionServiceTest extends IntegrationSpecification { @Autowired ClientIdRegistry clientIdRegistry @Autowired - SessionService mqttSessionService + MqttSessionService mqttSessionService def "subscriber should create and re-use mqtt session"() { given: diff --git a/application/src/test/groovy/javasabr/mqtt/application/integration/service/SubscribtionServiceTest.groovy b/application/src/test/groovy/javasabr/mqtt/broker/application/service/SubscribtionServiceTest.groovy similarity index 97% rename from application/src/test/groovy/javasabr/mqtt/application/integration/service/SubscribtionServiceTest.groovy rename to application/src/test/groovy/javasabr/mqtt/broker/application/service/SubscribtionServiceTest.groovy index d6a1d96f..1f5c859d 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/integration/service/SubscribtionServiceTest.groovy +++ b/application/src/test/groovy/javasabr/mqtt/broker/application/service/SubscribtionServiceTest.groovy @@ -1,8 +1,8 @@ -package javasabr.mqtt.application.integration.service +package javasabr.mqtt.broker.application.service import com.hivemq.client.mqtt.datatypes.MqttQos import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5SubAckException -import javasabr.mqtt.application.integration.IntegrationSpecification +import javasabr.mqtt.broker.application.IntegrationSpecification import javasabr.mqtt.model.ActionResult import javasabr.mqtt.model.subscriber.SingleSubscriber import javasabr.mqtt.service.ClientIdRegistry @@ -14,7 +14,7 @@ import spock.lang.Unroll import java.util.concurrent.CompletionException import static com.hivemq.client.mqtt.datatypes.MqttQos.* -import static javasabr.mqtt.model.utils.TopicUtils.buildTopicName +import static javasabr.mqtt.model.util.TopicUtils.buildTopicName import static org.spockframework.util.Pair.of class SubscribtionServiceTest extends IntegrationSpecification { diff --git a/application/src/test/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule b/application/src/test/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule deleted file mode 100644 index 485e81c4..00000000 --- a/application/src/test/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule +++ /dev/null @@ -1,3 +0,0 @@ -moduleName=test-specification -moduleVersion=1.0 -extensionClasses=javasabr.mqtt.application.extension.SpecificationExtensions diff --git a/application/src/test/resources/log4j2.xml b/application/src/test/resources/log4j2.xml index 0f78067a..881eaa86 100644 --- a/application/src/test/resources/log4j2.xml +++ b/application/src/test/resources/log4j2.xml @@ -6,7 +6,7 @@ - + diff --git a/buildSrc/src/main/groovy/configure-jacoco.gradle b/buildSrc/src/main/groovy/configure-jacoco.gradle new file mode 100644 index 00000000..3e77f6c3 --- /dev/null +++ b/buildSrc/src/main/groovy/configure-jacoco.gradle @@ -0,0 +1,12 @@ +plugins { + id "jacoco" +} + +jacocoTestReport { + dependsOn test + reports { + xml.required = false + csv.required = false + html.outputLocation = layout.buildDirectory.dir('jacocoHtml') + } +} diff --git a/buildSrc/src/main/groovy/configure-java.gradle b/buildSrc/src/main/groovy/configure-java.gradle index 027d5fdc..1e884758 100644 --- a/buildSrc/src/main/groovy/configure-java.gradle +++ b/buildSrc/src/main/groovy/configure-java.gradle @@ -2,6 +2,8 @@ import org.apache.tools.ant.filters.ReplaceTokens plugins { id("java") + id("java-test-fixtures") + id("configure-jacoco") } java { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e51cef81..730049e8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -38,6 +38,7 @@ moquette-broker = "0.17" rlib-network = { module = "javasabr.rlib:rlib-network", version.ref = "rlib" } rlib-logger-api = { module = "javasabr.rlib:rlib-logger-api", version.ref = "rlib" } rlib-logger-slf4j = { module = "javasabr.rlib:rlib-logger-slf4j", version.ref = "rlib" } +rlib-logger-impl = { module = "javasabr.rlib:rlib-logger-impl", version.ref = "rlib" } rlib-collections = { module = "javasabr.rlib:rlib-collections", version.ref = "rlib" } springboot-starter-core = { module = "org.springframework.boot:spring-boot-starter", version.ref = "springboot" } springboot-starter-log4j2 = { module = "org.springframework.boot:spring-boot-starter-log4j2", version.ref = "springboot" } diff --git a/model/build.gradle b/model/build.gradle index 6be210a1..df6832c1 100644 --- a/model/build.gradle +++ b/model/build.gradle @@ -1,10 +1,12 @@ plugins { id("java-library") id("configure-java") + id("groovy") } dependencies { api projects.base testImplementation projects.testSupport + testImplementation libs.rlib.logger.impl } \ No newline at end of file diff --git a/model/src/main/java/javasabr/mqtt/model/subscriber/SubscribeTopicFilter.java b/model/src/main/java/javasabr/mqtt/model/subscriber/SubscribeTopicFilter.java index 7fa192a2..6a647bd7 100644 --- a/model/src/main/java/javasabr/mqtt/model/subscriber/SubscribeTopicFilter.java +++ b/model/src/main/java/javasabr/mqtt/model/subscriber/SubscribeTopicFilter.java @@ -1,6 +1,6 @@ package javasabr.mqtt.model.subscriber; -import static javasabr.mqtt.model.utils.TopicUtils.buildTopicFilter; +import static javasabr.mqtt.model.util.TopicUtils.buildTopicFilter; import javasabr.mqtt.model.QoS; import javasabr.mqtt.model.SubscribeRetainHandling; diff --git a/model/src/main/java/javasabr/mqtt/model/topic/AbstractTopic.java b/model/src/main/java/javasabr/mqtt/model/topic/AbstractTopic.java index d757f46e..9c4b40df 100644 --- a/model/src/main/java/javasabr/mqtt/model/topic/AbstractTopic.java +++ b/model/src/main/java/javasabr/mqtt/model/topic/AbstractTopic.java @@ -1,7 +1,7 @@ package javasabr.mqtt.model.topic; import javasabr.mqtt.base.utils.DebugUtils; -import javasabr.mqtt.model.utils.TopicUtils; +import javasabr.mqtt.model.util.TopicUtils; import lombok.EqualsAndHashCode; import lombok.Getter; diff --git a/model/src/main/java/javasabr/mqtt/model/topic/TopicSubscribers.java b/model/src/main/java/javasabr/mqtt/model/topic/TopicSubscribers.java index 1ae347d4..9e6383fa 100644 --- a/model/src/main/java/javasabr/mqtt/model/topic/TopicSubscribers.java +++ b/model/src/main/java/javasabr/mqtt/model/topic/TopicSubscribers.java @@ -8,8 +8,8 @@ import javasabr.mqtt.model.subscriber.SingleSubscriber; import javasabr.mqtt.model.subscriber.SubscribeTopicFilter; import javasabr.mqtt.model.subscriber.Subscriber; -import javasabr.mqtt.model.utils.SubscriberUtils; -import javasabr.mqtt.model.utils.TopicUtils; +import javasabr.mqtt.model.util.SubscriberUtils; +import javasabr.mqtt.model.util.TopicUtils; import javasabr.rlib.collections.array.Array; import javasabr.rlib.collections.array.ArrayFactory; import javasabr.rlib.collections.array.LockableArray; diff --git a/model/src/main/java/javasabr/mqtt/model/utils/SubscriberUtils.java b/model/src/main/java/javasabr/mqtt/model/util/SubscriberUtils.java similarity index 96% rename from model/src/main/java/javasabr/mqtt/model/utils/SubscriberUtils.java rename to model/src/main/java/javasabr/mqtt/model/util/SubscriberUtils.java index e244920c..d1960c49 100644 --- a/model/src/main/java/javasabr/mqtt/model/utils/SubscriberUtils.java +++ b/model/src/main/java/javasabr/mqtt/model/util/SubscriberUtils.java @@ -1,4 +1,4 @@ -package javasabr.mqtt.model.utils; +package javasabr.mqtt.model.util; import javasabr.mqtt.model.MqttUser; import javasabr.mqtt.model.subscriber.SharedSubscriber; diff --git a/model/src/main/java/javasabr/mqtt/model/utils/TopicUtils.java b/model/src/main/java/javasabr/mqtt/model/util/TopicUtils.java similarity index 99% rename from model/src/main/java/javasabr/mqtt/model/utils/TopicUtils.java rename to model/src/main/java/javasabr/mqtt/model/util/TopicUtils.java index f7885c3d..ae052030 100644 --- a/model/src/main/java/javasabr/mqtt/model/utils/TopicUtils.java +++ b/model/src/main/java/javasabr/mqtt/model/util/TopicUtils.java @@ -1,4 +1,4 @@ -package javasabr.mqtt.model.utils; +package javasabr.mqtt.model.util; import javasabr.mqtt.model.topic.SharedTopicFilter; import javasabr.mqtt.model.topic.TopicFilter; diff --git a/model/src/main/java/javasabr/mqtt/model/utils/package-info.java b/model/src/main/java/javasabr/mqtt/model/util/package-info.java similarity index 61% rename from model/src/main/java/javasabr/mqtt/model/utils/package-info.java rename to model/src/main/java/javasabr/mqtt/model/util/package-info.java index 5f96d001..c4bb5fa9 100644 --- a/model/src/main/java/javasabr/mqtt/model/utils/package-info.java +++ b/model/src/main/java/javasabr/mqtt/model/util/package-info.java @@ -1,4 +1,4 @@ @NullMarked -package javasabr.mqtt.model.utils; +package javasabr.mqtt.model.util; import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/application/src/test/groovy/javasabr/mqtt/application/model/ActionResultTest.groovy b/model/src/test/groovy/javasabr/mqtt/model/ActionResultTest.groovy similarity index 71% rename from application/src/test/groovy/javasabr/mqtt/application/model/ActionResultTest.groovy rename to model/src/test/groovy/javasabr/mqtt/model/ActionResultTest.groovy index 827a9879..38f0cac8 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/model/ActionResultTest.groovy +++ b/model/src/test/groovy/javasabr/mqtt/model/ActionResultTest.groovy @@ -1,19 +1,17 @@ -package javasabr.mqtt.application.model +package javasabr.mqtt.model -import javasabr.mqtt.application.network.NetworkUnitSpecification -import javasabr.mqtt.model.ActionResult +import javasabr.mqtt.test.support.UnitSpecification import spock.lang.Unroll import static javasabr.mqtt.model.ActionResult.* -class ActionResultTest extends NetworkUnitSpecification { +class ActionResultTest extends UnitSpecification { @Unroll def "#first and #second == #result"( ActionResult first, ActionResult second, - ActionResult result - ) { + ActionResult result) { expect: first.and(second) == result where: diff --git a/application/src/test/groovy/javasabr/mqtt/application/model/TopicSubscriberTest.groovy b/model/src/test/groovy/javasabr/mqtt/model/TopicSubscriberTest.groovy similarity index 66% rename from application/src/test/groovy/javasabr/mqtt/application/model/TopicSubscriberTest.groovy rename to model/src/test/groovy/javasabr/mqtt/model/TopicSubscriberTest.groovy index 0eff2fee..ccb7e160 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/model/TopicSubscriberTest.groovy +++ b/model/src/test/groovy/javasabr/mqtt/model/TopicSubscriberTest.groovy @@ -1,19 +1,27 @@ -package javasabr.mqtt.application.model +package javasabr.mqtt.model -import javasabr.mqtt.application.network.NetworkUnitSpecification -import javasabr.mqtt.model.QoS import javasabr.mqtt.model.subscriber.SubscribeTopicFilter import javasabr.mqtt.model.topic.TopicFilter import javasabr.mqtt.model.topic.TopicName import javasabr.mqtt.model.topic.TopicSubscribers -import javasabr.mqtt.network.MqttClient +import javasabr.mqtt.test.support.UnitSpecification +import spock.lang.Shared import spock.lang.Unroll import static javasabr.mqtt.model.QoS.* -import static javasabr.mqtt.model.utils.TopicUtils.buildTopicFilter -import static javasabr.mqtt.model.utils.TopicUtils.buildTopicName +import static javasabr.mqtt.model.util.TopicUtils.buildTopicFilter +import static javasabr.mqtt.model.util.TopicUtils.buildTopicName -class TopicSubscriberTest extends NetworkUnitSpecification { +class TopicSubscriberTest extends UnitSpecification { + + @Shared + MqttUser defaultUser = Mock(MqttUser) + @Shared + MqttUser newUser1 = Mock(MqttUser) + @Shared + MqttUser newUser2 = Mock(MqttUser) + @Shared + MqttUser newUser3 = Mock(MqttUser) @Unroll def "should choose #matchedQos from #subscriberQos"( @@ -21,17 +29,17 @@ class TopicSubscriberTest extends NetworkUnitSpecification { TopicName topicNames, QoS[] subscriberQos, QoS[] matchedQos, - MqttClient[] mqttClients) { + MqttUser[] users) { given: - SubscribeTopicFilter[] subscribeFilters = new SubscribeTopicFilter[mqttClients.length] - mqttClients.eachWithIndex { MqttClient entry, int i -> + SubscribeTopicFilter[] subscribeFilters = new SubscribeTopicFilter[users.length] + users.eachWithIndex { MqttUser entry, int i -> subscribeFilters[i] = new SubscribeTopicFilter(topicFilters[i], subscriberQos[i]) } def topicSubscriber = new TopicSubscribers() when: - topicSubscriber.addSubscriber(mqttClients[0], subscribeFilters[0]) - topicSubscriber.addSubscriber(mqttClients[1], subscribeFilters[1]) - topicSubscriber.addSubscriber(mqttClients[2], subscribeFilters[2]) + topicSubscriber.addSubscriber(users[0], subscribeFilters[0]) + topicSubscriber.addSubscriber(users[1], subscribeFilters[1]) + topicSubscriber.addSubscriber(users[2], subscribeFilters[2]) then: def subscribers = topicSubscriber.matches(topicNames) subscribers.size() == matchedQos.size() @@ -63,11 +71,11 @@ class TopicSubscriberTest extends NetworkUnitSpecification { [AT_LEAST_ONCE], [AT_LEAST_ONCE, AT_MOST_ONCE, EXACTLY_ONCE] ] - mqttClients << [ - [defaultMqtt311Client, defaultMqtt311Client, defaultMqtt311Client], - [defaultMqtt311Client, defaultMqtt311Client, defaultMqtt311Client], - [defaultMqtt311Client, defaultMqtt311Client, defaultMqtt311Client], - [newMqtt311Client(), newMqtt311Client(), newMqtt311Client()] + users << [ + [defaultUser, defaultUser, defaultUser], + [defaultUser, defaultUser, defaultUser], + [defaultUser, defaultUser, defaultUser], + [newUser1, newUser2, newUser3] ] } } diff --git a/application/src/test/groovy/javasabr/mqtt/application/model/TopicTest.groovy b/model/src/test/groovy/javasabr/mqtt/model/TopicTest.groovy similarity index 95% rename from application/src/test/groovy/javasabr/mqtt/application/model/TopicTest.groovy rename to model/src/test/groovy/javasabr/mqtt/model/TopicTest.groovy index 4dce31d2..f6a285df 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/model/TopicTest.groovy +++ b/model/src/test/groovy/javasabr/mqtt/model/TopicTest.groovy @@ -1,13 +1,12 @@ -package javasabr.mqtt.application.model +package javasabr.mqtt.model + -import javasabr.mqtt.model.MqttUser -import javasabr.mqtt.model.QoS import javasabr.mqtt.model.subscriber.SubscribeTopicFilter import javasabr.mqtt.model.topic.TopicSubscribers import spock.lang.Specification import spock.lang.Unroll -import static javasabr.mqtt.model.utils.TopicUtils.* +import static javasabr.mqtt.model.util.TopicUtils.* class TopicTest extends Specification { diff --git a/application/src/test/groovy/javasabr/mqtt/application/util/TopicUtilsTest.groovy b/model/src/test/groovy/javasabr/mqtt/model/util/TopicUtilsTest.groovy similarity index 85% rename from application/src/test/groovy/javasabr/mqtt/application/util/TopicUtilsTest.groovy rename to model/src/test/groovy/javasabr/mqtt/model/util/TopicUtilsTest.groovy index e3ebbcca..c377ec64 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/util/TopicUtilsTest.groovy +++ b/model/src/test/groovy/javasabr/mqtt/model/util/TopicUtilsTest.groovy @@ -1,11 +1,11 @@ -package javasabr.mqtt.application.util +package javasabr.mqtt.model.util -import spock.lang.Specification +import javasabr.mqtt.test.support.UnitSpecification import spock.lang.Unroll -import static javasabr.mqtt.model.utils.TopicUtils.* +import static javasabr.mqtt.model.util.TopicUtils.* -class TopicUtilsTest extends Specification { +class TopicUtilsTest extends UnitSpecification { @Unroll def "should create valid topic name: [#topicName]"() { diff --git a/network/build.gradle b/network/build.gradle index c0e178c5..50870b2e 100644 --- a/network/build.gradle +++ b/network/build.gradle @@ -1,6 +1,7 @@ plugins { id("java-library") id("configure-java") + id("groovy") } dependencies { @@ -10,4 +11,6 @@ dependencies { api libs.rlib.logger.api testImplementation projects.testSupport + testImplementation libs.rlib.logger.impl + testFixturesApi projects.testSupport } \ No newline at end of file diff --git a/network/src/main/java/javasabr/mqtt/network/MqttClient.java b/network/src/main/java/javasabr/mqtt/network/MqttClient.java index 6901ddd6..dfcafaf7 100644 --- a/network/src/main/java/javasabr/mqtt/network/MqttClient.java +++ b/network/src/main/java/javasabr/mqtt/network/MqttClient.java @@ -3,8 +3,8 @@ import java.util.concurrent.CompletableFuture; import javasabr.mqtt.model.MqttClientConnectionConfig; import javasabr.mqtt.model.MqttUser; -import javasabr.mqtt.network.packet.out.ConnectAck311OutPacket; -import javasabr.mqtt.network.packet.out.MqttWritablePacket; +import javasabr.mqtt.network.message.out.ConnectAckMqtt311OutMessage; +import javasabr.mqtt.network.message.out.MqttOutMessage; import org.jspecify.annotations.Nullable; import reactor.core.publisher.Mono; @@ -18,7 +18,7 @@ interface UnsafeMqttClient extends MqttClient { void session(@Nullable MqttSession session); - void reject(ConnectAck311OutPacket connectAsk); + void reject(ConnectAckMqtt311OutMessage connectAsk); Mono release(); } @@ -30,7 +30,7 @@ interface UnsafeMqttClient extends MqttClient { MqttClientConnectionConfig connectionConfig(); - void send(MqttWritablePacket packet); + void send(MqttOutMessage packet); - CompletableFuture sendWithFeedback(MqttWritablePacket packet); + CompletableFuture sendWithFeedback(MqttOutMessage packet); } diff --git a/network/src/main/java/javasabr/mqtt/network/MqttConnection.java b/network/src/main/java/javasabr/mqtt/network/MqttConnection.java index c22d92c9..5e654bb4 100644 --- a/network/src/main/java/javasabr/mqtt/network/MqttConnection.java +++ b/network/src/main/java/javasabr/mqtt/network/MqttConnection.java @@ -5,8 +5,8 @@ import javasabr.mqtt.model.MqttServerConnectionConfig; import javasabr.mqtt.model.MqttVersion; import javasabr.mqtt.network.MqttClient.UnsafeMqttClient; -import javasabr.mqtt.network.packet.MqttPacketReader; -import javasabr.mqtt.network.packet.MqttPacketWriter; +import javasabr.mqtt.network.message.MqttMessageReader; +import javasabr.mqtt.network.message.MqttMessageWriter; import javasabr.rlib.network.BufferAllocator; import javasabr.rlib.network.Network; import javasabr.rlib.network.impl.AbstractConnection; @@ -80,7 +80,7 @@ public MqttClient client() { } private NetworkPacketReader createPacketReader() { - return new MqttPacketReader( + return new MqttMessageReader( this, this::updateLastActivity, this::handleReceivedPacket, @@ -88,7 +88,7 @@ private NetworkPacketReader createPacketReader() { } private NetworkPacketWriter createPacketWriter() { - return new MqttPacketWriter( + return new MqttMessageWriter( this, this::updateLastActivity, this::nextPacketToWrite, diff --git a/network/src/main/java/javasabr/mqtt/network/MqttSession.java b/network/src/main/java/javasabr/mqtt/network/MqttSession.java index 15a71192..187ca659 100644 --- a/network/src/main/java/javasabr/mqtt/network/MqttSession.java +++ b/network/src/main/java/javasabr/mqtt/network/MqttSession.java @@ -2,8 +2,8 @@ import javasabr.mqtt.model.subscriber.SubscribeTopicFilter; import javasabr.mqtt.model.topic.TopicFilter; -import javasabr.mqtt.network.packet.HasPacketId; -import javasabr.mqtt.network.packet.in.PublishInPacket; +import javasabr.mqtt.network.message.HasMessageId; +import javasabr.mqtt.network.message.in.PublishMqttInMessage; import javasabr.rlib.functions.TriConsumer; public interface MqttSession { @@ -24,9 +24,9 @@ interface PendingMessageHandler { /** * @return true if pending packet can be removed. */ - boolean handleResponse(MqttClient client, HasPacketId response); + boolean handleResponse(MqttClient client, HasMessageId response); - default void resend(MqttClient client, PublishInPacket packet, int packetId) {} + default void resend(MqttClient client, PublishMqttInMessage packet, int packetId) {} } String clientId(); @@ -48,13 +48,13 @@ default void resend(MqttClient client, PublishInPacket packet, int packetId) {} boolean hasOutPending(int packetId); - void registerOutPublish(PublishInPacket publish, PendingMessageHandler handler, int packetId); + void registerOutPublish(PublishMqttInMessage publish, PendingMessageHandler handler, int packetId); - void registerInPublish(PublishInPacket publish, PendingMessageHandler handler, int packetId); + void registerInPublish(PublishMqttInMessage publish, PendingMessageHandler handler, int packetId); - void updateOutPendingPacket(MqttClient client, HasPacketId response); + void updateOutPendingPacket(MqttClient client, HasMessageId response); - void updateInPendingPacket(MqttClient client, HasPacketId response); + void updateInPendingPacket(MqttClient client, HasMessageId response); void forEachTopicFilter( A arg1, diff --git a/network/src/main/java/javasabr/mqtt/network/client/AbstractMqttClient.java b/network/src/main/java/javasabr/mqtt/network/impl/AbstractMqttClient.java similarity index 86% rename from network/src/main/java/javasabr/mqtt/network/client/AbstractMqttClient.java rename to network/src/main/java/javasabr/mqtt/network/impl/AbstractMqttClient.java index 954070c7..63481ecf 100644 --- a/network/src/main/java/javasabr/mqtt/network/client/AbstractMqttClient.java +++ b/network/src/main/java/javasabr/mqtt/network/impl/AbstractMqttClient.java @@ -1,4 +1,4 @@ -package javasabr.mqtt.network.client; +package javasabr.mqtt.network.impl; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicBoolean; @@ -8,8 +8,8 @@ import javasabr.mqtt.network.MqttConnection; import javasabr.mqtt.network.MqttSession; import javasabr.mqtt.network.handler.MqttClientReleaseHandler; -import javasabr.mqtt.network.packet.out.ConnectAck311OutPacket; -import javasabr.mqtt.network.packet.out.MqttWritablePacket; +import javasabr.mqtt.network.message.out.ConnectAckMqtt311OutMessage; +import javasabr.mqtt.network.message.out.MqttOutMessage; import lombok.AccessLevel; import lombok.CustomLog; import lombok.Getter; @@ -49,19 +49,19 @@ public AbstractMqttClient(MqttConnection connection, MqttClientReleaseHandler re } @Override - public void send(MqttWritablePacket packet) { + public void send(MqttOutMessage packet) { log.debug(clientId, packet.name(), packet, "[%s] Send to client packet:[%s] %s"::formatted); connection.send(packet); } @Override - public CompletableFuture sendWithFeedback(MqttWritablePacket packet) { + public CompletableFuture sendWithFeedback(MqttOutMessage packet) { log.debug(clientId, packet.name(), packet, "[%s] Send to client packet:[%s] %s"::formatted); return connection.sendWithFeedback(packet); } @Override - public void reject(ConnectAck311OutPacket connectAsk) { + public void reject(ConnectAckMqtt311OutMessage connectAsk) { connection .sendWithFeedback(connectAsk) .thenAccept(_ -> connection.close()); diff --git a/network/src/main/java/javasabr/mqtt/network/client/ExternalMqttClient.java b/network/src/main/java/javasabr/mqtt/network/impl/ExternalMqttClient.java similarity index 91% rename from network/src/main/java/javasabr/mqtt/network/client/ExternalMqttClient.java rename to network/src/main/java/javasabr/mqtt/network/impl/ExternalMqttClient.java index b51ed805..41a9400c 100644 --- a/network/src/main/java/javasabr/mqtt/network/client/ExternalMqttClient.java +++ b/network/src/main/java/javasabr/mqtt/network/impl/ExternalMqttClient.java @@ -1,4 +1,4 @@ -package javasabr.mqtt.network.client; +package javasabr.mqtt.network.impl; import javasabr.mqtt.base.utils.DebugUtils; import javasabr.mqtt.network.MqttConnection; diff --git a/network/src/main/java/javasabr/mqtt/network/client/InternalMqttClient.java b/network/src/main/java/javasabr/mqtt/network/impl/InternalMqttClient.java similarity index 91% rename from network/src/main/java/javasabr/mqtt/network/client/InternalMqttClient.java rename to network/src/main/java/javasabr/mqtt/network/impl/InternalMqttClient.java index 6fa07737..b9aba103 100644 --- a/network/src/main/java/javasabr/mqtt/network/client/InternalMqttClient.java +++ b/network/src/main/java/javasabr/mqtt/network/impl/InternalMqttClient.java @@ -1,4 +1,4 @@ -package javasabr.mqtt.network.client; +package javasabr.mqtt.network.impl; import javasabr.mqtt.base.utils.DebugUtils; import javasabr.mqtt.network.MqttConnection; diff --git a/network/src/main/java/javasabr/mqtt/network/message/HasMessageId.java b/network/src/main/java/javasabr/mqtt/network/message/HasMessageId.java new file mode 100644 index 00000000..5b1d1353 --- /dev/null +++ b/network/src/main/java/javasabr/mqtt/network/message/HasMessageId.java @@ -0,0 +1,9 @@ +package javasabr.mqtt.network.message; + +import javasabr.mqtt.network.MqttConnection; +import javasabr.rlib.network.packet.NetworkPacket; + +public interface HasMessageId extends NetworkPacket { + + int messageId(); +} diff --git a/network/src/main/java/javasabr/mqtt/network/message/MqttMessageReader.java b/network/src/main/java/javasabr/mqtt/network/message/MqttMessageReader.java new file mode 100644 index 00000000..b99293dc --- /dev/null +++ b/network/src/main/java/javasabr/mqtt/network/message/MqttMessageReader.java @@ -0,0 +1,105 @@ +package javasabr.mqtt.network.message; + +import java.nio.ByteBuffer; +import java.util.NoSuchElementException; +import java.util.function.Consumer; +import javasabr.mqtt.network.MqttConnection; +import javasabr.mqtt.network.message.in.AuthenticationMqttInMessage; +import javasabr.mqtt.network.message.in.ConnectAckMqttInMessage; +import javasabr.mqtt.network.message.in.ConnectMqttInMessage; +import javasabr.mqtt.network.message.in.DisconnectMqttInMessage; +import javasabr.mqtt.network.message.in.MqttInMessage; +import javasabr.mqtt.network.message.in.PingRequestMqttInMessage; +import javasabr.mqtt.network.message.in.PingResponseMqttInMessage; +import javasabr.mqtt.network.message.in.PublishAckMqttInMessage; +import javasabr.mqtt.network.message.in.PublishCompleteMqttInMessage; +import javasabr.mqtt.network.message.in.PublishMqttInMessage; +import javasabr.mqtt.network.message.in.PublishReceivedMqttInMessage; +import javasabr.mqtt.network.message.in.PublishReleaseMqttInMessage; +import javasabr.mqtt.network.message.in.SubscribeAckMqttInMessage; +import javasabr.mqtt.network.message.in.SubscribeMqttInMessage; +import javasabr.mqtt.network.message.in.UnsubscribeAckMqttInMessage; +import javasabr.mqtt.network.message.in.UnsubscribeMqttInMessage; +import javasabr.mqtt.network.util.MqttDataUtils; +import javasabr.rlib.common.util.ArrayUtils; +import javasabr.rlib.common.util.NumberUtils; +import javasabr.rlib.functions.ByteFunction; +import javasabr.rlib.network.packet.impl.AbstractNetworkPacketReader; +import lombok.CustomLog; +import org.jspecify.annotations.Nullable; + +@CustomLog +public class MqttMessageReader extends AbstractNetworkPacketReader { + + private static final int PACKET_LENGTH_START_BYTE = 2; + + private static final ByteFunction[] PACKET_FACTORIES = ArrayUtils.array( + info -> { + throw new NoSuchElementException("Unknown MQTT message with id:[0]"); + }, + ConnectMqttInMessage::new, + ConnectAckMqttInMessage::new, + PublishMqttInMessage::new, + PublishAckMqttInMessage::new, + PublishReceivedMqttInMessage::new, + PublishReleaseMqttInMessage::new, + PublishCompleteMqttInMessage::new, + SubscribeMqttInMessage::new, + SubscribeAckMqttInMessage::new, + UnsubscribeMqttInMessage::new, + UnsubscribeAckMqttInMessage::new, + PingRequestMqttInMessage::new, + PingResponseMqttInMessage::new, + DisconnectMqttInMessage::new, + AuthenticationMqttInMessage::new); + + public MqttMessageReader( + MqttConnection connection, + Runnable updateActivityFunction, + Consumer readPacketHandler, + int maxPacketsByRead) { + super(connection, updateActivityFunction, readPacketHandler, maxPacketsByRead); + } + + @Override + protected boolean canStartReadPacket(ByteBuffer buffer) { + return buffer.remaining() >= PACKET_LENGTH_START_BYTE; + } + + @Override + protected int readFullPacketLength(ByteBuffer buffer) { + // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901021 + int prevPos = buffer.position(); + + // skip first byte of packet type + buffer.get(); + int dataSize = MqttDataUtils.readMbi(buffer); + if (dataSize == -1) { + return -1; + } + + int readBytes = buffer.position() - prevPos; + return dataSize + readBytes; + } + + @Nullable + @Override + protected MqttInMessage createPacketFor( + ByteBuffer buffer, + int startPacketPosition, + int packetLength, + int dataLength) { + + // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901021 + int firstByte = Byte.toUnsignedInt(buffer.get(startPacketPosition)); + byte type = NumberUtils.getHighByteBits(firstByte); + byte info = NumberUtils.getLowByteBits(firstByte); + + try { + return PACKET_FACTORIES[type].apply(info); + } catch (NoSuchElementException | NullPointerException e) { + log.error(e.getMessage()); + return null; + } + } +} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/MqttPacketType.java b/network/src/main/java/javasabr/mqtt/network/message/MqttMessageType.java similarity index 91% rename from network/src/main/java/javasabr/mqtt/network/packet/MqttPacketType.java rename to network/src/main/java/javasabr/mqtt/network/message/MqttMessageType.java index dd5f3af9..92c1f128 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/MqttPacketType.java +++ b/network/src/main/java/javasabr/mqtt/network/message/MqttMessageType.java @@ -1,16 +1,18 @@ -package javasabr.mqtt.network.packet; +package javasabr.mqtt.network.message; import lombok.AccessLevel; +import lombok.CustomLog; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.experimental.Accessors; import lombok.experimental.FieldDefaults; @Getter +@CustomLog @Accessors(fluent = true) @RequiredArgsConstructor @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) -public enum MqttPacketType { +public enum MqttMessageType { RESERVED(0), /** * After a Network Connection is established by a Client to a Server, the first Packet sent from the Client to the @@ -103,13 +105,14 @@ public enum MqttPacketType { */ INVALID(16); - private static final MqttPacketType[] VALUES = values(); + private static final MqttMessageType[] VALUES = values(); - public static MqttPacketType fromByte(byte packetType) { - if (packetType < 0 || packetType > AUTHENTICATE.typeIndex()) { + public static MqttMessageType fromByte(byte messageType) { + if (messageType < 0 || messageType > AUTHENTICATE.typeIndex()) { + log.warning(messageType, "Invalid message type:[%s]"::formatted); return INVALID; } else { - return VALUES[packetType]; + return VALUES[messageType]; } } diff --git a/network/src/main/java/javasabr/mqtt/network/packet/MqttPacketWriter.java b/network/src/main/java/javasabr/mqtt/network/message/MqttMessageWriter.java similarity index 81% rename from network/src/main/java/javasabr/mqtt/network/packet/MqttPacketWriter.java rename to network/src/main/java/javasabr/mqtt/network/message/MqttMessageWriter.java index 1f9c6820..eb80337d 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/MqttPacketWriter.java +++ b/network/src/main/java/javasabr/mqtt/network/message/MqttMessageWriter.java @@ -1,21 +1,21 @@ -package javasabr.mqtt.network.packet; +package javasabr.mqtt.network.message; import java.nio.ByteBuffer; import java.util.function.Consumer; import java.util.function.Supplier; import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.out.MqttWritablePacket; -import javasabr.mqtt.network.utils.MqttDataUtils; +import javasabr.mqtt.network.message.out.MqttOutMessage; +import javasabr.mqtt.network.util.MqttDataUtils; import javasabr.rlib.functions.ObjBoolConsumer; import javasabr.rlib.network.packet.WritableNetworkPacket; import javasabr.rlib.network.packet.impl.AbstractNetworkPacketWriter; import org.jspecify.annotations.Nullable; -public class MqttPacketWriter extends AbstractNetworkPacketWriter { +public class MqttMessageWriter extends AbstractNetworkPacketWriter { public static final int DATA_OFFSET = 5; - public MqttPacketWriter( + public MqttMessageWriter( MqttConnection connection, Runnable updateActivityFunction, Supplier<@Nullable WritableNetworkPacket> packetProvider, @@ -36,18 +36,17 @@ protected int totalSize(WritableNetworkPacket packet, int expect @Override protected boolean onBeforeSerialize( - MqttWritablePacket packet, + MqttOutMessage packet, int expectedLength, int totalSize, ByteBuffer writeBuffer) { - writeBuffer.clear() - .position(DATA_OFFSET); + writeBuffer.clear().position(DATA_OFFSET); return true; } @Override protected boolean onAfterSerialize( - MqttWritablePacket packet, + MqttOutMessage packet, int expectedLength, int totalSize, ByteBuffer writeBuffer) { diff --git a/network/src/main/java/javasabr/mqtt/network/message/in/AuthenticationMqttInMessage.java b/network/src/main/java/javasabr/mqtt/network/message/in/AuthenticationMqttInMessage.java new file mode 100644 index 00000000..c53008ef --- /dev/null +++ b/network/src/main/java/javasabr/mqtt/network/message/in/AuthenticationMqttInMessage.java @@ -0,0 +1,106 @@ +package javasabr.mqtt.network.message.in; + +import java.nio.ByteBuffer; +import java.util.EnumSet; +import java.util.Set; +import javasabr.mqtt.model.PacketProperty; +import javasabr.mqtt.model.reason.code.AuthenticateReasonCode; +import javasabr.mqtt.network.MqttConnection; +import javasabr.mqtt.network.message.MqttMessageType; +import javasabr.rlib.common.util.ArrayUtils; +import javasabr.rlib.common.util.StringUtils; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.experimental.Accessors; +import lombok.experimental.FieldDefaults; + +/** + * Authentication exchange. + */ +@Getter +@Accessors(fluent = true) +@FieldDefaults(level = AccessLevel.PRIVATE) +public class AuthenticationMqttInMessage extends MqttInMessage { + + private static final byte MESSAGE_TYPE = (byte) MqttMessageType.AUTHENTICATE.ordinal(); + + private static final Set AVAILABLE_PROPERTIES = EnumSet.of( + /* + Followed by a UTF-8 Encoded String containing the name of the authentication method. It is a Protocol + Error to omit the Authentication Method or to include it more than once. Refer to section 4.12 for more + information about extended authentication. + */ + PacketProperty.AUTHENTICATION_METHOD, + /* + Followed by Binary Data containing authentication data. It is a Protocol Error to include Authentication + Data more than once. The contents of this data are defined by the authentication method. Refer to + section 4.12 for more information about extended authentication. + */ + PacketProperty.AUTHENTICATION_DATA, + /* + Followed by the UTF-8 Encoded String representing the reason for the disconnect. This Reason String is + human readable, designed for diagnostics and SHOULD NOT be parsed by the receiver. + + The sender MUST NOT send this property if it would increase the size of the AUTH packet beyond the + Maximum Packet Size specified by the receiver [MQTT-3.15.2-2]. It is a Protocol Error to include the + Reason String more than once. + */ + PacketProperty.REASON_STRING, + /* + Followed by UTF-8 String Pair. This property may be used to provide additional diagnostic or other + information. The sender MUST NOT send this property if it would increase the size of the AUTH packet + beyond the Maximum Packet Size specified by the receiver [MQTT-3.15.2-3]. The User Property is + allowed to appear multiple times to represent multiple name, value pairs. The same name is allowed to + appear more than once. + */ + PacketProperty.USER_PROPERTY); + + AuthenticateReasonCode reasonCode; + + // properties + String reason; + String authenticationMethod; + + byte[] authenticationData; + + public AuthenticationMqttInMessage(byte info) { + super(info); + this.reasonCode = AuthenticateReasonCode.SUCCESS; + this.reason = StringUtils.EMPTY; + this.authenticationMethod = StringUtils.EMPTY; + this.authenticationData = ArrayUtils.EMPTY_BYTE_ARRAY; + } + + @Override + public byte messageType() { + return MESSAGE_TYPE; + } + + @Override + protected void readVariableHeader(MqttConnection connection, ByteBuffer buffer) { + // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901219 + reasonCode = AuthenticateReasonCode.of(readByteUnsigned(buffer)); + } + + @Override + protected Set availableProperties() { + return AVAILABLE_PROPERTIES; + } + + @Override + protected void applyProperty(PacketProperty property, byte[] value) { + switch (property) { + case AUTHENTICATION_DATA -> authenticationData = value; + default -> unexpectedProperty(property); + } + } + + @Override + protected void applyProperty(PacketProperty property, String value) { + switch (property) { + case REASON_STRING -> reason = value; + case AUTHENTICATION_METHOD -> authenticationMethod = value; + default -> unexpectedProperty(property); + } + } +} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/in/ConnectAckInPacket.java b/network/src/main/java/javasabr/mqtt/network/message/in/ConnectAckMqttInMessage.java similarity index 82% rename from network/src/main/java/javasabr/mqtt/network/packet/in/ConnectAckInPacket.java rename to network/src/main/java/javasabr/mqtt/network/message/in/ConnectAckMqttInMessage.java index f727a255..4c7610df 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/in/ConnectAckInPacket.java +++ b/network/src/main/java/javasabr/mqtt/network/message/in/ConnectAckMqttInMessage.java @@ -1,4 +1,4 @@ -package javasabr.mqtt.network.packet.in; +package javasabr.mqtt.network.message.in; import java.nio.ByteBuffer; import java.util.EnumSet; @@ -10,20 +10,25 @@ import javasabr.mqtt.model.data.type.StringPair; import javasabr.mqtt.model.reason.code.ConnectAckReasonCode; import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.MqttPacketType; +import javasabr.mqtt.network.message.MqttMessageType; import javasabr.rlib.collections.array.MutableArray; import javasabr.rlib.common.util.ArrayUtils; import javasabr.rlib.common.util.NumberUtils; import javasabr.rlib.common.util.StringUtils; +import lombok.AccessLevel; import lombok.Getter; +import lombok.experimental.Accessors; +import lombok.experimental.FieldDefaults; /** * Acknowledge connection request. */ @Getter -public class ConnectAckInPacket extends MqttReadablePacket { +@Accessors(fluent = true) +@FieldDefaults(level = AccessLevel.PRIVATE) +public class ConnectAckMqttInMessage extends MqttInMessage { - private static final byte PACKET_TYPE = (byte) MqttPacketType.CONNECT_ACK.ordinal(); + private static final byte MESSAGE_TYPE = (byte) MqttMessageType.CONNECT_ACK.ordinal(); private static final Set AVAILABLE_PROPERTIES = EnumSet.of( /* @@ -234,8 +239,8 @@ public class ConnectAckInPacket extends MqttReadablePacket { * Connect Reason code from this table. If a Server sends a CONNACK packet containing a Reason code of 128 or greater * it MUST then close the Network Connection */ - private ConnectAckReasonCode reasonCode; - private QoS maximumQos; + ConnectAckReasonCode reasonCode; + QoS maximumQos; /** * The Session Present flag informs the Client whether the Server is using Session State from a previous connection @@ -243,29 +248,29 @@ public class ConnectAckInPacket extends MqttReadablePacket { * accepts a connection with Clean Start set to 1, the Server MUST set Session Present to 0 in the CONNACK packet in * addition to setting a 0x00 (Success) Reason Code in the CONNACK packet */ - private boolean sessionPresent; + boolean sessionPresent; // properties - private String assignedClientId; - private String reason; - private String responseInformation; - private String authenticationMethod; - private String serverReference; - private byte[] authenticationData; - - private long sessionExpiryInterval; - - private int receiveMaxPublishes; - private int maxPacketSize; - private int topicAliasMaxValue; - private int serverKeepAlive; - - private boolean retainAvailable; - private boolean wildcardSubscriptionAvailable; - private boolean sharedSubscriptionAvailable; - private boolean subscriptionIdAvailable; - - public ConnectAckInPacket(byte info) { + String assignedClientId; + String reason; + String responseInformation; + String authenticationMethod; + String serverReference; + byte[] authenticationData; + + long sessionExpiryInterval; + + int receiveMaxPublishes; + int maxPacketSize; + int topicAliasMaxValue; + int serverKeepAlive; + + boolean retainAvailable; + boolean wildcardSubscriptionAvailable; + boolean sharedSubscriptionAvailable; + boolean subscriptionIdAvailable; + + public ConnectAckMqttInMessage(byte info) { super(info); this.userProperties = MutableArray.ofType(StringPair.class); this.reasonCode = ConnectAckReasonCode.SUCCESS; @@ -288,126 +293,71 @@ public ConnectAckInPacket(byte info) { } @Override - public byte packetType() { - return PACKET_TYPE; + public byte messageType() { + return MESSAGE_TYPE; } @Override protected void readVariableHeader(MqttConnection connection, ByteBuffer buffer) { - // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718035 sessionPresent = readByteUnsigned(buffer) == 1; reasonCode = ConnectAckReasonCode.of(connection.isSupported(MqttVersion.MQTT_5), readByteUnsigned(buffer)); } @Override - protected Set getAvailableProperties() { + protected Set availableProperties() { return AVAILABLE_PROPERTIES; } @Override protected void applyProperty(PacketProperty property, byte[] value) { switch (property) { - case AUTHENTICATION_DATA: { - authenticationData = value; - break; - } - default: { - unexpectedProperty(property); - } + case AUTHENTICATION_DATA -> authenticationData = value; + default -> unexpectedProperty(property); } } @Override protected void applyProperty(PacketProperty property, String value) { switch (property) { - case REASON_STRING: { - reason = value; - break; - } - case ASSIGNED_CLIENT_IDENTIFIER: { - assignedClientId = value; - break; - } - case RESPONSE_INFORMATION: { - responseInformation = value; - break; - } - case AUTHENTICATION_METHOD: { - authenticationMethod = value; - break; - } - case SERVER_REFERENCE: { - serverReference = value; - break; - } - default: { - unexpectedProperty(property); - } + case REASON_STRING -> reason = value; + case ASSIGNED_CLIENT_IDENTIFIER -> assignedClientId = value; + case RESPONSE_INFORMATION -> responseInformation = value; + case AUTHENTICATION_METHOD -> authenticationMethod = value; + case SERVER_REFERENCE -> serverReference = value; + default -> unexpectedProperty(property); } } @Override protected void applyProperty(PacketProperty property, long value) { switch (property) { - case WILDCARD_SUBSCRIPTION_AVAILABLE: { - wildcardSubscriptionAvailable = NumberUtils.toBoolean(value); - break; - } - case SHARED_SUBSCRIPTION_AVAILABLE: { - sharedSubscriptionAvailable = NumberUtils.toBoolean(value); - break; - } - case SUBSCRIPTION_IDENTIFIER_AVAILABLE: { - subscriptionIdAvailable = NumberUtils.toBoolean(value); - break; - } - case RETAIN_AVAILABLE: { - retainAvailable = NumberUtils.toBoolean(value); - break; - } - case RECEIVE_MAXIMUM_PUBLISH: { - receiveMaxPublishes = (int) NumberUtils.validate( - value, - MqttProperties.RECEIVE_MAXIMUM_MIN, - MqttProperties.RECEIVE_MAXIMUM_MAX); - break; - } - case MAXIMUM_QOS: { - maximumQos = QoS.of((int) value); - break; - } - case SERVER_KEEP_ALIVE: { - serverKeepAlive = NumberUtils.validate( - (int) value, - MqttProperties.SERVER_KEEP_ALIVE_MIN, - MqttProperties.SERVER_KEEP_ALIVE_MAX); - break; - } - case TOPIC_ALIAS_MAXIMUM: { - topicAliasMaxValue = NumberUtils.validate( - (int) value, - MqttProperties.TOPIC_ALIAS_MIN, - MqttProperties.TOPIC_ALIAS_MAX); - break; - } - case SESSION_EXPIRY_INTERVAL: { - sessionExpiryInterval = NumberUtils.validate( - value, - MqttProperties.SESSION_EXPIRY_INTERVAL_MIN, - MqttProperties.SESSION_EXPIRY_INTERVAL_INFINITY); - break; - } - case MAXIMUM_PACKET_SIZE: { - maxPacketSize = NumberUtils.validate( - (int) value, - MqttProperties.MAXIMUM_PACKET_SIZE_MIN, - MqttProperties.MAXIMUM_PACKET_SIZE_MAX); - break; - } - default: { - unexpectedProperty(property); - } + case WILDCARD_SUBSCRIPTION_AVAILABLE -> wildcardSubscriptionAvailable = NumberUtils.toBoolean(value); + case SHARED_SUBSCRIPTION_AVAILABLE -> sharedSubscriptionAvailable = NumberUtils.toBoolean(value); + case SUBSCRIPTION_IDENTIFIER_AVAILABLE -> subscriptionIdAvailable = NumberUtils.toBoolean(value); + case RETAIN_AVAILABLE -> retainAvailable = NumberUtils.toBoolean(value); + case RECEIVE_MAXIMUM_PUBLISH -> receiveMaxPublishes = (int) NumberUtils.validate( + value, + MqttProperties.RECEIVE_MAXIMUM_MIN, + MqttProperties.RECEIVE_MAXIMUM_MAX); + case MAXIMUM_QOS -> maximumQos = QoS.of((int) value); + case SERVER_KEEP_ALIVE -> serverKeepAlive = NumberUtils.validate( + (int) value, + MqttProperties.SERVER_KEEP_ALIVE_MIN, + MqttProperties.SERVER_KEEP_ALIVE_MAX); + case TOPIC_ALIAS_MAXIMUM -> topicAliasMaxValue = NumberUtils.validate( + (int) value, + MqttProperties.TOPIC_ALIAS_MIN, + MqttProperties.TOPIC_ALIAS_MAX); + case SESSION_EXPIRY_INTERVAL -> sessionExpiryInterval = NumberUtils.validate( + value, + MqttProperties.SESSION_EXPIRY_INTERVAL_MIN, + MqttProperties.SESSION_EXPIRY_INTERVAL_INFINITY); + case MAXIMUM_PACKET_SIZE -> maxPacketSize = NumberUtils.validate( + (int) value, + MqttProperties.MAXIMUM_PACKET_SIZE_MIN, + MqttProperties.MAXIMUM_PACKET_SIZE_MAX); + default -> unexpectedProperty(property); } } } diff --git a/network/src/main/java/javasabr/mqtt/network/packet/in/ConnectInPacket.java b/network/src/main/java/javasabr/mqtt/network/message/in/ConnectMqttInMessage.java similarity index 89% rename from network/src/main/java/javasabr/mqtt/network/packet/in/ConnectInPacket.java rename to network/src/main/java/javasabr/mqtt/network/message/in/ConnectMqttInMessage.java index 5fb4e1b4..e8117ccb 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/in/ConnectInPacket.java +++ b/network/src/main/java/javasabr/mqtt/network/message/in/ConnectMqttInMessage.java @@ -1,4 +1,4 @@ -package javasabr.mqtt.network.packet.in; +package javasabr.mqtt.network.message.in; import java.nio.ByteBuffer; import java.util.EnumSet; @@ -10,7 +10,7 @@ import javasabr.mqtt.model.exception.ConnectionRejectException; import javasabr.mqtt.model.reason.code.ConnectAckReasonCode; import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.MqttPacketType; +import javasabr.mqtt.network.message.MqttMessageType; import javasabr.rlib.common.util.ArrayUtils; import javasabr.rlib.common.util.NumberUtils; import javasabr.rlib.common.util.StringUtils; @@ -25,9 +25,9 @@ @Getter @Accessors(fluent = true, chain = false) @FieldDefaults(level = AccessLevel.PRIVATE) -public class ConnectInPacket extends MqttReadablePacket { +public class ConnectMqttInMessage extends MqttInMessage { - private static final byte PACKET_TYPE = (byte) MqttPacketType.CONNECT.ordinal(); + private static final byte MESSAGE_TYPE = (byte) MqttMessageType.CONNECT.ordinal(); static { DebugUtils.registerIncludedFields("clientId", "keepAlive", "cleanStart", "mqttVersion"); @@ -221,13 +221,13 @@ public class ConnectInPacket extends MqttReadablePacket { boolean requestResponseInformation = false; boolean requestProblemInformation = false; - public ConnectInPacket(byte info) { + public ConnectMqttInMessage(byte info) { super(info); } @Override - public byte packetType() { - return PACKET_TYPE; + public byte messageType() { + return MESSAGE_TYPE; } @Override @@ -343,78 +343,48 @@ protected boolean isPropertiesSupported(MqttConnection connection, ByteBuffer bu } @Override - protected Set getAvailableProperties() { + protected Set availableProperties() { return AVAILABLE_PROPERTIES; } @Override protected void applyProperty(PacketProperty property, byte[] value) { switch (property) { - case AUTHENTICATION_DATA: { - authenticationData = value; - break; - } - default: { - unexpectedProperty(property); - } + case AUTHENTICATION_DATA -> authenticationData = value; + default -> unexpectedProperty(property); } } @Override protected void applyProperty(PacketProperty property, String value) { switch (property) { - case AUTHENTICATION_METHOD: { - authenticationMethod = value; - break; - } - default: { - unexpectedProperty(property); - } + case AUTHENTICATION_METHOD -> authenticationMethod = value; + default -> unexpectedProperty(property); } } @Override protected void applyProperty(PacketProperty property, long value) { switch (property) { - case REQUEST_RESPONSE_INFORMATION: { - requestResponseInformation = NumberUtils.toBoolean(value); - break; - } - case REQUEST_PROBLEM_INFORMATION: { - requestProblemInformation = NumberUtils.toBoolean(value); - break; - } - case RECEIVE_MAXIMUM_PUBLISH: { - receiveMaxPublishes = NumberUtils.validate( - (int) value, - MqttProperties.RECEIVE_MAXIMUM_MIN, - MqttProperties.RECEIVE_MAXIMUM_MAX); - break; - } - case TOPIC_ALIAS_MAXIMUM: { - topicAliasMaxValue = NumberUtils.validate( - (int) value, - MqttProperties.TOPIC_ALIAS_MIN, - MqttProperties.TOPIC_ALIAS_MAX); - break; - } - case SESSION_EXPIRY_INTERVAL: { - sessionExpiryInterval = NumberUtils.validate( - value, - MqttProperties.SESSION_EXPIRY_INTERVAL_MIN, - MqttProperties.SESSION_EXPIRY_INTERVAL_INFINITY); - break; - } - case MAXIMUM_PACKET_SIZE: { - maxPacketSize = NumberUtils.validate( - (int) value, - MqttProperties.MAXIMUM_PACKET_SIZE_MIN, - MqttProperties.MAXIMUM_PACKET_SIZE_MAX); - break; - } - default: { - unexpectedProperty(property); - } + case REQUEST_RESPONSE_INFORMATION -> requestResponseInformation = NumberUtils.toBoolean(value); + case REQUEST_PROBLEM_INFORMATION -> requestProblemInformation = NumberUtils.toBoolean(value); + case RECEIVE_MAXIMUM_PUBLISH -> receiveMaxPublishes = NumberUtils.validate( + (int) value, + MqttProperties.RECEIVE_MAXIMUM_MIN, + MqttProperties.RECEIVE_MAXIMUM_MAX); + case TOPIC_ALIAS_MAXIMUM -> topicAliasMaxValue = NumberUtils.validate( + (int) value, + MqttProperties.TOPIC_ALIAS_MIN, + MqttProperties.TOPIC_ALIAS_MAX); + case SESSION_EXPIRY_INTERVAL -> sessionExpiryInterval = NumberUtils.validate( + value, + MqttProperties.SESSION_EXPIRY_INTERVAL_MIN, + MqttProperties.SESSION_EXPIRY_INTERVAL_INFINITY); + case MAXIMUM_PACKET_SIZE -> maxPacketSize = NumberUtils.validate( + (int) value, + MqttProperties.MAXIMUM_PACKET_SIZE_MIN, + MqttProperties.MAXIMUM_PACKET_SIZE_MAX); + default -> unexpectedProperty(property); } } } diff --git a/network/src/main/java/javasabr/mqtt/network/message/in/DisconnectMqttInMessage.java b/network/src/main/java/javasabr/mqtt/network/message/in/DisconnectMqttInMessage.java new file mode 100644 index 00000000..91b11220 --- /dev/null +++ b/network/src/main/java/javasabr/mqtt/network/message/in/DisconnectMqttInMessage.java @@ -0,0 +1,141 @@ +package javasabr.mqtt.network.message.in; + +import java.nio.ByteBuffer; +import java.util.EnumSet; +import java.util.Set; +import javasabr.mqtt.base.utils.DebugUtils; +import javasabr.mqtt.model.MqttProperties; +import javasabr.mqtt.model.MqttVersion; +import javasabr.mqtt.model.PacketProperty; +import javasabr.mqtt.model.reason.code.DisconnectReasonCode; +import javasabr.mqtt.network.MqttConnection; +import javasabr.mqtt.network.message.MqttMessageType; +import javasabr.rlib.common.util.StringUtils; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.experimental.Accessors; +import lombok.experimental.FieldDefaults; + +/** + * Disconnect notification. + */ +@Getter +@Accessors(fluent = true) +@FieldDefaults(level = AccessLevel.PRIVATE) +public class DisconnectMqttInMessage extends MqttInMessage { + + public static final byte MESSAGE_TYPE = (byte) MqttMessageType.DISCONNECT.ordinal(); + + static { + DebugUtils.registerIncludedFields("reasonCode"); + } + + private static final Set AVAILABLE_PROPERTIES = EnumSet.of( + /* + If the Session Expiry Interval is absent, the Session Expiry Interval in the CONNECT packet is used. + + The Session Expiry Interval MUST NOT be sent on a DISCONNECT by the Server [MQTT-3.14.2-2]. + + If the Session Expiry Interval in the CONNECT packet was zero, then it is a Protocol Error to set a non + zero Session Expiry Interval in the DISCONNECT packet sent by the Client. If such a non-zero Session + Expiry Interval is received by the Server, it does not treat it as a valid DISCONNECT packet. The Server + uses DISCONNECT with Reason Code 0x82 (Protocol Error) as described in + */ + PacketProperty.SESSION_EXPIRY_INTERVAL, + /* + The sender MUST NOT send this Property if it would increase the size of the DISCONNECT packet + beyond the Maximum Packet Size specified by the receiver [MQTT-3.14.2-3]. It is a Protocol Error to + include the Reason String more than once. + */ + PacketProperty.REASON_STRING, + /* + Followed by UTF-8 String Pair. This property may be used to provide additional diagnostic or other + information. The sender MUST NOT send this property if it would increase the size of the DISCONNECT + packet beyond the Maximum Packet Size specified by the receiver [MQTT-3.14.2-4]. The User Property is + allowed to appear multiple times to represent multiple name, value pairs. The same name is allowed to + appear more than once. + */ + PacketProperty.USER_PROPERTY, + /* + The Server sends DISCONNECT including a Server Reference and Reason Code {0x9C (Use another + 2601 server)} or 0x9D (Server moved) as described in section 4.13. + */ + PacketProperty.SERVER_REFERENCE); + + DisconnectReasonCode reasonCode; + + // properties + String reason; + String serverReference; + + long sessionExpiryInterval; + + public DisconnectMqttInMessage(byte info) { + super(info); + this.reasonCode = DisconnectReasonCode.NORMAL_DISCONNECTION; + this.reason = StringUtils.EMPTY; + this.serverReference = StringUtils.EMPTY; + this.sessionExpiryInterval = MqttProperties.SESSION_EXPIRY_INTERVAL_DEFAULT; + } + + @Override + public byte messageType() { + return MESSAGE_TYPE; + } + + @Override + protected void readImpl(MqttConnection connection, ByteBuffer buffer) { + this.sessionExpiryInterval = connection + .clientConnectionConfig() + .sessionExpiryInterval(); + super.readImpl(connection, buffer); + } + + @Override + protected void readVariableHeader(MqttConnection connection, ByteBuffer buffer) { + // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901207 + if (connection.isSupported(MqttVersion.MQTT_5) && buffer.hasRemaining()) { + reasonCode = DisconnectReasonCode.of(readByteUnsigned(buffer)); + } + } + + @Override + protected boolean isPropertiesSupported(MqttConnection connection, ByteBuffer buffer) { + return connection.isSupported(MqttVersion.MQTT_5) && buffer.hasRemaining(); + } + + @Override + protected Set availableProperties() { + return AVAILABLE_PROPERTIES; + } + + @Override + protected void applyProperty(PacketProperty property, long value) { + switch (property) { + case SESSION_EXPIRY_INTERVAL: { + sessionExpiryInterval = value; + break; + } + default: { + unexpectedProperty(property); + } + } + } + + @Override + protected void applyProperty(PacketProperty property, String value) { + switch (property) { + case REASON_STRING: { + reason = value; + break; + } + case SERVER_REFERENCE: { + serverReference = value; + break; + } + default: { + unexpectedProperty(property); + } + } + } +} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/in/MqttReadablePacket.java b/network/src/main/java/javasabr/mqtt/network/message/in/MqttInMessage.java similarity index 95% rename from network/src/main/java/javasabr/mqtt/network/packet/in/MqttReadablePacket.java rename to network/src/main/java/javasabr/mqtt/network/message/in/MqttInMessage.java index 029e1691..f1e4fd31 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/in/MqttReadablePacket.java +++ b/network/src/main/java/javasabr/mqtt/network/message/in/MqttInMessage.java @@ -1,4 +1,4 @@ -package javasabr.mqtt.network.packet.in; +package javasabr.mqtt.network.message.in; import java.nio.ByteBuffer; import java.nio.CharBuffer; @@ -18,7 +18,7 @@ import javasabr.mqtt.model.exception.MqttException; import javasabr.mqtt.model.reason.code.ConnectAckReasonCode; import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.utils.MqttDataUtils; +import javasabr.mqtt.network.util.MqttDataUtils; import javasabr.rlib.collections.array.Array; import javasabr.rlib.collections.array.MutableArray; import javasabr.rlib.common.util.ArrayUtils; @@ -31,7 +31,7 @@ @Accessors(fluent = true, chain = false) @FieldDefaults(level = AccessLevel.PROTECTED) -public abstract class MqttReadablePacket extends AbstractReadableNetworkPacket { +public abstract class MqttInMessage extends AbstractReadableNetworkPacket { static { DebugUtils.registerIncludedFields("userProperties"); @@ -67,9 +67,9 @@ private record Utf8Decoder(CharsetDecoder decoder, ByteBuffer inBuffer, CharBuff @Nullable Exception exception; - protected MqttReadablePacket(byte info) {} + protected MqttInMessage(byte info) {} - public abstract byte packetType(); + public abstract byte messageType(); public Array userProperties() { return userProperties == null ? EMPTY_PROPERTIES : userProperties; @@ -104,7 +104,7 @@ protected boolean isPropertiesSupported(MqttConnection connection, ByteBuffer bu protected void readVariableHeader(MqttConnection connection, ByteBuffer buffer) {} protected void readProperties(MqttConnection connection, ByteBuffer buffer) { - readProperties(connection, buffer, getAvailableProperties()); + readProperties(connection, buffer, availableProperties()); } protected void readPayload(MqttConnection connection, ByteBuffer buffer) {} @@ -164,7 +164,7 @@ protected void readProperties(MqttConnection connection, ByteBuffer buffer, Set< } } - protected Set getAvailableProperties() { + protected Set availableProperties() { return Collections.emptySet(); } diff --git a/network/src/main/java/javasabr/mqtt/network/message/in/PingRequestMqttInMessage.java b/network/src/main/java/javasabr/mqtt/network/message/in/PingRequestMqttInMessage.java new file mode 100644 index 00000000..80774f3b --- /dev/null +++ b/network/src/main/java/javasabr/mqtt/network/message/in/PingRequestMqttInMessage.java @@ -0,0 +1,20 @@ +package javasabr.mqtt.network.message.in; + +import javasabr.mqtt.network.message.MqttMessageType; + +/** + * PING request. + */ +public class PingRequestMqttInMessage extends MqttInMessage { + + public static final byte MESSAGE_TYPE = (byte) MqttMessageType.PING_REQUEST.ordinal(); + + public PingRequestMqttInMessage(byte info) { + super(info); + } + + @Override + public byte messageType() { + return MESSAGE_TYPE; + } +} diff --git a/network/src/main/java/javasabr/mqtt/network/message/in/PingResponseMqttInMessage.java b/network/src/main/java/javasabr/mqtt/network/message/in/PingResponseMqttInMessage.java new file mode 100644 index 00000000..d439ea10 --- /dev/null +++ b/network/src/main/java/javasabr/mqtt/network/message/in/PingResponseMqttInMessage.java @@ -0,0 +1,20 @@ +package javasabr.mqtt.network.message.in; + +import javasabr.mqtt.network.message.MqttMessageType; + +/** + * PING response. + */ +public class PingResponseMqttInMessage extends MqttInMessage { + + public static final byte MESSAGE_TYPE = (byte) MqttMessageType.PING_RESPONSE.ordinal(); + + public PingResponseMqttInMessage(byte info) { + super(info); + } + + @Override + public byte messageType() { + return MESSAGE_TYPE; + } +} diff --git a/network/src/main/java/javasabr/mqtt/network/message/in/PublishAckMqttInMessage.java b/network/src/main/java/javasabr/mqtt/network/message/in/PublishAckMqttInMessage.java new file mode 100644 index 00000000..72bc28ec --- /dev/null +++ b/network/src/main/java/javasabr/mqtt/network/message/in/PublishAckMqttInMessage.java @@ -0,0 +1,99 @@ +package javasabr.mqtt.network.message.in; + +import java.nio.ByteBuffer; +import java.util.EnumSet; +import java.util.Set; +import javasabr.mqtt.base.utils.DebugUtils; +import javasabr.mqtt.model.MqttVersion; +import javasabr.mqtt.model.PacketProperty; +import javasabr.mqtt.model.reason.code.PublishAckReasonCode; +import javasabr.mqtt.network.MqttConnection; +import javasabr.mqtt.network.message.HasMessageId; +import javasabr.mqtt.network.message.MqttMessageType; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.experimental.Accessors; +import lombok.experimental.FieldDefaults; + +/** + * Publish acknowledgment (QoS 1). + */ +@Getter +@Accessors(fluent = true, chain = false) +@FieldDefaults(level = AccessLevel.PRIVATE) +public class PublishAckMqttInMessage extends MqttInMessage implements HasMessageId { + + private static final int MESSAGE_TYPE = MqttMessageType.PUBLISH_ACK.ordinal(); + + static { + DebugUtils.registerIncludedFields("reasonCode", "messageId"); + } + + private static final Set AVAILABLE_PROPERTIES = EnumSet.of( + /* + Followed by the UTF-8 Encoded String representing the reason associated with this response. This + Reason String is a human readable string designed for diagnostics and is not intended to be parsed by + the receiver. + + The sender uses this value to give additional information to the receiver. The sender MUST NOT send + this property if it would increase the size of the PUBACK packet beyond the Maximum Packet Size + specified by the receiver [MQTT-3.4.2-2]. It is a Protocol Error to include the Reason String more than + once. + */ + PacketProperty.REASON_STRING, + /* + Followed by UTF-8 String Pair. This property can be used to provide additional diagnostic or other + information. The sender MUST NOT send this property if it would increase the size of the PUBACK + packet beyond the Maximum Packet Size specified by the receiver [MQTT-3.4.2-3]. The User Property is + allowed to appear multiple times to represent multiple name, value pairs. The same name is allowed to + appear more than once. + */ + PacketProperty.USER_PROPERTY); + + PublishAckReasonCode reasonCode; + int messageId; + + // properties + String reason; + + public PublishAckMqttInMessage(byte info) { + super(info); + this.reasonCode = PublishAckReasonCode.SUCCESS; + this.reason = ""; + } + + @Override + public byte messageType() { + return (byte) MESSAGE_TYPE; + } + + @Override + protected void readVariableHeader(MqttConnection connection, ByteBuffer buffer) { + + // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718045 + messageId = readShortUnsigned(buffer); + + // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901123 + if (connection.isSupported(MqttVersion.MQTT_5) && buffer.hasRemaining()) { + reasonCode = PublishAckReasonCode.ofValue(readByteUnsigned(buffer)); + } + } + + @Override + protected boolean isPropertiesSupported(MqttConnection connection, ByteBuffer buffer) { + return connection.isSupported(MqttVersion.MQTT_5) && buffer.hasRemaining(); + } + + @Override + protected Set availableProperties() { + return AVAILABLE_PROPERTIES; + } + + @Override + protected void applyProperty(PacketProperty property, String value) { + switch (property) { + case REASON_STRING -> reason = value; + default -> unexpectedProperty(property); + } + } +} diff --git a/network/src/main/java/javasabr/mqtt/network/message/in/PublishCompleteMqttInMessage.java b/network/src/main/java/javasabr/mqtt/network/message/in/PublishCompleteMqttInMessage.java new file mode 100644 index 00000000..f0dc0a63 --- /dev/null +++ b/network/src/main/java/javasabr/mqtt/network/message/in/PublishCompleteMqttInMessage.java @@ -0,0 +1,101 @@ +package javasabr.mqtt.network.message.in; + +import java.nio.ByteBuffer; +import java.util.EnumSet; +import java.util.Set; +import javasabr.mqtt.base.utils.DebugUtils; +import javasabr.mqtt.model.MqttVersion; +import javasabr.mqtt.model.PacketProperty; +import javasabr.mqtt.model.reason.code.PublishCompletedReasonCode; +import javasabr.mqtt.network.MqttConnection; +import javasabr.mqtt.network.message.HasMessageId; +import javasabr.mqtt.network.message.MqttMessageType; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.experimental.Accessors; +import lombok.experimental.FieldDefaults; + +/** + * Publish complete (QoS 2 delivery part 3). + */ +@Getter +@Accessors(fluent = true, chain = false) +@FieldDefaults(level = AccessLevel.PRIVATE) +public class PublishCompleteMqttInMessage extends MqttInMessage implements HasMessageId { + + private static final byte MESSAGE_TYPE = (byte) MqttMessageType.PUBLISH_COMPLETED.ordinal(); + + static { + DebugUtils.registerIncludedFields("reasonCode", "messageId"); + } + + private static final Set AVAILABLE_PROPERTIES = EnumSet.of( + /* + Followed by the UTF-8 Encoded String representing the reason associated with this response. This + Reason String is human readable, designed for diagnostics and SHOULD NOT be parsed by the + receiver. + + The sender uses this value to give additional information to the receiver. The sender MUST NOT send + this Property if it would increase the size of the PUBREL packet beyond the Maximum Packet Size + specified by the receiver [MQTT-3.6.2-2]. It is a Protocol Error to include the Reason String more than + once. + */ + PacketProperty.REASON_STRING, + /* + Followed by UTF-8 String Pair. This property can be used to provide additional diagnostic or other + information for the PUBREL. The sender MUST NOT send this property if it would increase the size of the + PUBREL packet beyond the Maximum Packet Size specified by the receiver [MQTT-3.6.2-3]. The User + Property is allowed to appear multiple times to represent multiple name, value pairs. The same name is + allowed to appear more than once + */ + PacketProperty.USER_PROPERTY); + + PublishCompletedReasonCode reasonCode; + int messageId; + + // properties + String reason; + + public PublishCompleteMqttInMessage(byte info) { + super(info); + this.reasonCode = PublishCompletedReasonCode.SUCCESS; + this.reason = ""; + } + + @Override + public byte messageType() { + return MESSAGE_TYPE; + } + + @Override + protected void readVariableHeader(MqttConnection connection, ByteBuffer buffer) { + super.readVariableHeader(connection, buffer); + + // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718083 + messageId = readShortUnsigned(buffer); + + // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901154 + if (connection.isSupported(MqttVersion.MQTT_5) && buffer.hasRemaining()) { + reasonCode = PublishCompletedReasonCode.of(readByteUnsigned(buffer)); + } + } + + @Override + protected boolean isPropertiesSupported(MqttConnection connection, ByteBuffer buffer) { + // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901154 + return super.isPropertiesSupported(connection, buffer) && buffer.hasRemaining(); + } + + @Override + protected Set availableProperties() { + return AVAILABLE_PROPERTIES; + } + + @Override + protected void applyProperty(PacketProperty property, String value) { + switch (property) { + case REASON_STRING -> reason = value; + default -> unexpectedProperty(property); + } + } +} diff --git a/network/src/main/java/javasabr/mqtt/network/message/in/PublishMqttInMessage.java b/network/src/main/java/javasabr/mqtt/network/message/in/PublishMqttInMessage.java new file mode 100644 index 00000000..7e16a56e --- /dev/null +++ b/network/src/main/java/javasabr/mqtt/network/message/in/PublishMqttInMessage.java @@ -0,0 +1,347 @@ +package javasabr.mqtt.network.message.in; + +import static javasabr.mqtt.model.util.TopicUtils.EMPTY_TOPIC_NAME; +import static javasabr.mqtt.model.util.TopicUtils.buildTopicName; + +import java.nio.ByteBuffer; +import java.util.EnumSet; +import java.util.Set; +import javasabr.mqtt.base.utils.DebugUtils; +import javasabr.mqtt.model.MqttProperties; +import javasabr.mqtt.model.PacketProperty; +import javasabr.mqtt.model.QoS; +import javasabr.mqtt.model.topic.TopicName; +import javasabr.mqtt.network.MqttConnection; +import javasabr.mqtt.network.message.MqttMessageType; +import javasabr.rlib.collections.array.ArrayFactory; +import javasabr.rlib.collections.array.IntArray; +import javasabr.rlib.collections.array.MutableIntArray; +import javasabr.rlib.common.util.ArrayUtils; +import javasabr.rlib.common.util.NumberUtils; +import javasabr.rlib.common.util.StringUtils; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.experimental.Accessors; +import lombok.experimental.FieldDefaults; + +/** + * Publish message. + */ +@Getter +@Accessors(fluent = true) +@FieldDefaults(level = AccessLevel.PRIVATE) +public class PublishMqttInMessage extends MqttInMessage { + + private static final byte MESSAGE_TYPE = (byte) MqttMessageType.PUBLISH.ordinal(); + + static { + DebugUtils.registerIncludedFields("topicName", "qos", "duplicate", "messageId"); + } + + private static final Set AVAILABLE_PROPERTIES = EnumSet.of( + /* + Followed by the value of the Payload Format Indicator, either of: + • 0 (0x00) Byte Indicates that the Payload is unspecified bytes, which is equivalent to not sending a + Payload Format Indicator. + • 1 (0x01) Byte Indicates that the Payload is UTF-8 Encoded Character Data. The UTF-8 data in + the Payload MUST be well-formed UTF-8 as defined by the Unicode specification [Unicode] + and restated in RFC 3629 [RFC3629]. + + A Server MUST send the Payload Format Indicator unaltered to all subscribers receiving the Application + 1563 Message [MQTT-3.3.2-4]. The receiver MAY validate that the Payload is of the format indicated, and if it + is not send a PUBACK, PUBREC, or DISCONNECT with Reason Code of 0x99 (Payload format invalid) + as described in section 4.13. Refer to section 5.4.9 for information about security issues in validating the + payload format. + */ + PacketProperty.PAYLOAD_FORMAT_INDICATOR, + /* + Followed by the Four Byte Integer representing the Message Expiry Interval. + + If present, the Four Byte value is the lifetime of the Application Message in seconds. If the Message + Expiry Interval has passed and the Server has not managed to start onward delivery to a matching + subscriber, then it MUST delete the copy of the message for that subscriber [MQTT-3.3.2-5]. + + If absent, the Application Message does not expire. + + The PUBLISH packet sent to a Client by the Server MUST contain a Message Expiry Interval set to the + received value minus the time that the Application Message has been waiting in the Server [MQTT-3.3.2- + 6]. Refer to section 4.1 for details and limitations of stored state. + */ + PacketProperty.MESSAGE_EXPIRY_INTERVAL, + /* + Followed by the Two Byte integer representing the Topic Alias value. It is a Protocol Error to include the + Topic Alias value more than once. + + A Topic Alias is an integer value that is used to identify the Topic instead of using the Topic Name. This + reduces the size of the PUBLISH packet, and is useful when the Topic Names are long and the same + Topic Names are used repetitively within a Network Connection. + + The sender decides whether to use a Topic Alias and chooses the value. It sets a Topic Alias mapping by + including a non-zero length Topic Name and a Topic Alias in the PUBLISH packet. The receiver + processes the PUBLISH as normal but also sets the specified Topic Alias mapping to this Topic Name. + + If a Topic Alias mapping has been set at the receiver, a sender can send a PUBLISH packet that contains + that Topic Alias and a zero length Topic Name. The receiver then treats the incoming PUBLISH as if it + had contained the Topic Name of the Topic Alias. + + A sender can modify the Topic Alias mapping by sending another PUBLISH in the same Network + Connection with the same Topic Alias value and a different non-zero length Topic Name. + + Topic Alias mappings exist only within a Network Connection and last only for the lifetime of that Network + Connection. A receiver MUST NOT carry forward any Topic Alias mappings from one Network + Connection to another [MQTT-3.3.2-7]. + + A Topic Alias of 0 is not permitted. A sender MUST NOT send a PUBLISH packet containing a Topic + Alias which has the value 0 [MQTT-3.3.2-8]. + + A Client MUST NOT send a PUBLISH packet with a Topic Alias greater than the Topic Alias Maximum + value returned by the Server in the CONNACK packet [MQTT-3.3.2-9]. A Client MUST accept all Topic + Alias values greater than 0 and less than or equal to the Topic Alias Maximum value that it sent in the + CONNECT packet [MQTT-3.3.2-10]. + + A Server MUST NOT send a PUBLISH packet with a Topic Alias greater than the Topic Alias Maximum + value sent by the Client in the CONNECT packet [MQTT-3.3.2-11]. A Server MUST accept all Topic Alias + values greater than 0 and less than or equal to the Topic Alias Maximum value that it returned in the + CONNACK packet [MQTT-3.3.2-12]. + + The Topic Alias mappings used by the Client and Server are independent from each other. Thus, when a + Client sends a PUBLISH containing a Topic Alias value of 1 to a Server and the Server sends a PUBLISH + with a Topic Alias value of 1 to that Client they will in general be referring to different Topics. + */ + PacketProperty.TOPIC_ALIAS, + /* + Followed by a UTF-8 Encoded String which is used as the Topic Name for a response message. The + Response Topic MUST be a UTF-8 Encoded String as defined in section 1.5.4 [MQTT-3.3.2-13]. The + Response Topic MUST NOT contain wildcard characters [MQTT-3.3.2-14]. It is a Protocol Error to include + the Response Topic more than once. The presence of a Response Topic identifies the Message as a + Request. + + Refer to section 4.10 for more information about Request / Response. + + The Server MUST send the Response Topic unaltered to all subscribers receiving the Application + Message [MQTT-3.3.2-15]. + */ + PacketProperty.RESPONSE_TOPIC, + /* + Followed by Binary Data. The Correlation Data is used by the sender of the Request Message to identify + which request the Response Message is for when it is received. It is a Protocol Error to include + Correlation Data more than once. If the Correlation Data is not present, the Requester does not require + any correlation data. + + The Server MUST send the Correlation Data unaltered to all subscribers receiving the Application + Message [MQTT-3.3.2-16]. The value of the Correlation Data only has meaning to the sender of the + Request Message and receiver of the Response Message. + */ + PacketProperty.CORRELATION_DATA, + /* + Followed by a UTF-8 String Pair. The User Property is allowed to appear multiple times to represent + multiple name, value pairs. The same name is allowed to appear more than once. + + The Server MUST send all User Properties unaltered in a PUBLISH packet when forwarding the + Application Message to a Client [MQTT-3.3.2-17]. The Server MUST maintain the order of User + Properties when forwarding the Application Message [MQTT-3.3.2-18]. + */ + PacketProperty.USER_PROPERTY, + /* + Followed by a Variable Byte Integer representing the identifier of the subscription. + + The Subscription Identifier can have the value of 1 to 268,435,455. It is a Protocol Error if the + Subscription Identifier has a value of 0. Multiple Subscription Identifiers will be included if the + publication + is the result of a match to more than one subscription, in this case their order is not significant. + */ + PacketProperty.SUBSCRIPTION_IDENTIFIER, + /* + Followed by a UTF-8 Encoded String describing the content of the Application Message. The Content + Type MUST be a UTF-8 Encoded String as defined in section 1.5.4 [MQTT-3.3.2-19]. + It is a Protocol Error to include the Content Type more than once. The value of the Content Type is + defined by the sending and receiving application. + + A Server MUST send the Content Type unaltered to all subscribers receiving the Application Message + [MQTT-3.3.2-20]. + */ + PacketProperty.CONTENT_TYPE); + + /** + * This field indicates the level of assurance for delivery of an Application Message. The QoS levels are shown + * below. + *

+ * 0 - 00 At most once delivery 1 --01 At least once delivery 2 - 10 Exactly once delivery - - 11 Reserved – must not + * be used + *

+ * If the Server included a Maximum QoS in its CONNACK response to a Client and it receives a PUBLISH packet with a + * QoS greater than this, then it uses DISCONNECT with Reason Code 0x9B (QoS not supported) as described in section + * 4.13 Handling errors. + *

+ * A PUBLISH Packet MUST NOT have both QoS bits set to 1 [MQTT-3.3.1-4]. If a Server or Client receives a PUBLISH + * packet which has both QoS bits set to 1 it is a Malformed Packet. Use DISCONNECT with Reason Code 0x81 (Malformed + * Packet) as described in + */ + final QoS qos; + + /** + * If the DUP flag is set to 0, it indicates that this is the first occasion that the Client or Server has attempted + * to send this PUBLISH packet. If the DUP flag is set to 1, it indicates that this might be re-delivery of an earlier + * attempt to send the packet. + *

+ * The DUP flag MUST be set to 1 by the Client or Server when it attempts to re-deliver a PUBLISH packet + * [MQTT-3.3.1-1]. The DUP flag MUST be set to 0 for all QoS 0 messages [MQTT-3.3.1-2]. + *

+ * The value of the DUP flag from an incoming PUBLISH packet is not propagated when the PUBLISH packet is sent to + * subscribers by the Server. The DUP flag in the outgoing PUBLISH packet is set independently to the incoming PUBLISH + * packet, its value MUST be determined solely by whether the outgoing PUBLISH packet is a retransmission + */ + final boolean duplicate; + + /** + * If the RETAIN flag is set to 1 in a PUBLISH packet sent by a Client to a Server, the Server MUST replace any + * existing retained message for this topic and store the Application Message [MQTT-3.3.1-5], so that it can be + * delivered to future subscribers whose subscriptions match its Topic Name. If the Payload contains zero bytes it is + * processed normally by the Server but any retained message with the same topic name MUST be removed and any future + * subscribers for the topic will not receive a retained message [MQTT1476 3.3.1-6]. A retained message with a Payload + * containing zero bytes MUST NOT be stored as a retained message on the Server [MQTT-3.3.1-7]. + *

+ * If the RETAIN flag is 0 in a PUBLISH packet sent by a Client to a Server, the Server MUST NOT store the message as + * a retained message and MUST NOT remove or replace any existing retained message [MQTT-3.3.1-8]. + *

+ * If the Server included Retain Available in its CONNACK response to a Client with its value set to 0 and it receives + * a PUBLISH packet with the RETAIN flag is set to 1, then it uses the DISCONNECT Reason Code of 0x9A (Retain not + * supported) as described in section 4.13. + *

+ * When a new Non-shared Subscription is made, the last retained message, if any, on each matching topic name is sent + * to the Client as directed by the Retain Handling Subscription Option. These messages are sent with the RETAIN flag + * set to 1. Which retained messages are sent is controlled by the Retain Handling Subscription Option. At the time of + * the Subscription: • If Retain Handling is set to 0 the Server MUST send the retained messages matching the Topic + * Filter of the subscription to the Client [MQTT-3.3.1-9]. • If Retain Handling is set to 1 then if the subscription + * did not already exist, the Server MUST send all retained message matching the Topic Filter of the subscription to + * the Client, and if the subscription did exist the Server MUST NOT send the retained messages. [MQTT-3.3.1-10]. • If + * Retain Handling is set to 2, the Server MUST NOT send the retained messages + *

+ * If the Server receives a PUBLISH packet with the RETAIN flag set to 1, and QoS 0 it SHOULD store the new QoS 0 + * message as the new retained message for that topic, but MAY choose to discard it at any time. If this happens there + * will be no retained message for that topic. + *

+ * If the current retained message for a Topic expires, it is discarded and there will be no retained message for that + * topic. + *

+ * The setting of the RETAIN flag in an Application Message forwarded by the Server from an established connection is + * controlled by the Retain As Published subscription option. Refer to section 3.8.3.1 for a definition of the + * Subscription Options. • If the value of Retain As Published subscription option is set to 0, the Server MUST set + * the RETAIN flag to 0 when forwarding an Application Message regardless of how the RETAIN flag was set in the + * received PUBLISH packet [MQTT-3.3.1-12]. • If the value of Retain As Published subscription option is set to 1, the + * Server MUST set the RETAIN flag equal to the RETAIN flag in the received PUBLISH packet + */ + final boolean retained; + + /** + * The Topic Name identifies the information channel to which Payload data is published. + *

+ * The Topic Name MUST be present as the first field in the PUBLISH packet Variable Header. It MUST be a UTF-8 Encoded + * String as defined in section 1.5.4 [MQTT-3.3.2-1]. + *

+ * Standards Track Work Product Copyright © OASIS Open 2019. All Rights Reserved. Page 56 of 137 The Topic Name in the + * PUBLISH packet MUST NOT contain wildcard characters [MQTT-3.3.2-2]. + *

+ * The Topic Name in a PUBLISH packet sent by a Server to a subscribing Client MUST match the Subscription’s Topic + * Filter according to the matching process defined in section 4.7 [MQTT-3.3.2-3]. However, as the Server is permitted + * to map the Topic Name to another name, it might not be the same as the Topic Name in the original PUBLISH packet. + *

+ * To reduce the size of the PUBLISH packet the sender can use a Topic Alias. The Topic Alias is described in section + * 3.3.2.3.4. It is a Protocol Error if the Topic Name is zero length and there is no Topic Alias. + */ + TopicName topicName; + + /** + * The Packet Identifier field is only present in PUBLISH packets where the QoS level is 1 or 2. Section 2.2.1 + * provides more information about Packet Identifiers. + */ + int messageId; + + byte[] payload; + + // properties + String responseTopic; + String contentType; + + IntArray subscriptionIds; + + byte[] correlationData; + + long messageExpiryInterval = MqttProperties.MESSAGE_EXPIRY_INTERVAL_UNDEFINED; + int topicAlias = MqttProperties.TOPIC_ALIAS_DEFAULT; + boolean payloadFormatIndicator = MqttProperties.PAYLOAD_FORMAT_INDICATOR_DEFAULT; + + public PublishMqttInMessage(byte info) { + super(info); + this.qos = QoS.of((info >> 1) & 0x03); + this.retained = NumberUtils.isSetBit(info, 0); + this.duplicate = NumberUtils.isSetBit(info, 3); + this.topicName = EMPTY_TOPIC_NAME; + this.responseTopic = StringUtils.EMPTY; + this.contentType = StringUtils.EMPTY; + this.correlationData = ArrayUtils.EMPTY_BYTE_ARRAY; + this.payload = ArrayUtils.EMPTY_BYTE_ARRAY; + this.subscriptionIds = IntArray.empty(); + } + + @Override + public byte messageType() { + return MESSAGE_TYPE; + } + + @Override + protected void readVariableHeader(MqttConnection connection, ByteBuffer buffer) { + // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718039 + topicName = buildTopicName(readString(buffer, Integer.MAX_VALUE)); + messageId = qos != QoS.AT_MOST_ONCE ? readShortUnsigned(buffer) : 0; + } + + @Override + protected void readPayload(MqttConnection connection, ByteBuffer buffer) { + // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718040 + payload = readPayload(buffer); + } + + @Override + protected Set availableProperties() { + return AVAILABLE_PROPERTIES; + } + + @Override + protected void applyProperty(PacketProperty property, long value) { + switch (property) { + case PAYLOAD_FORMAT_INDICATOR -> payloadFormatIndicator = NumberUtils.toBoolean(value); + case TOPIC_ALIAS -> topicAlias = NumberUtils.validate( + (int) value, + MqttProperties.TOPIC_ALIAS_MIN, + MqttProperties.TOPIC_ALIAS_MAX); + case MESSAGE_EXPIRY_INTERVAL -> messageExpiryInterval = value; + case SUBSCRIPTION_IDENTIFIER -> { + if (subscriptionIds == IntArray.empty()) { + subscriptionIds = ArrayFactory.mutableIntArray(); + } + if (subscriptionIds instanceof MutableIntArray array) { + array.add((int) value); + } + } + default -> unexpectedProperty(property); + } + } + + @Override + protected void applyProperty(PacketProperty property, String value) { + switch (property) { + case RESPONSE_TOPIC -> responseTopic = value; + case CONTENT_TYPE -> contentType = value; + default -> unexpectedProperty(property); + } + } + + @Override + protected void applyProperty(PacketProperty property, byte[] value) { + switch (property) { + case CORRELATION_DATA -> correlationData = value; + default -> unexpectedProperty(property); + } + } +} diff --git a/network/src/main/java/javasabr/mqtt/network/message/in/PublishReceivedMqttInMessage.java b/network/src/main/java/javasabr/mqtt/network/message/in/PublishReceivedMqttInMessage.java new file mode 100644 index 00000000..b4bbb54b --- /dev/null +++ b/network/src/main/java/javasabr/mqtt/network/message/in/PublishReceivedMqttInMessage.java @@ -0,0 +1,102 @@ +package javasabr.mqtt.network.message.in; + +import java.nio.ByteBuffer; +import java.util.EnumSet; +import java.util.Set; +import javasabr.mqtt.base.utils.DebugUtils; +import javasabr.mqtt.model.MqttVersion; +import javasabr.mqtt.model.PacketProperty; +import javasabr.mqtt.model.reason.code.PublishReceivedReasonCode; +import javasabr.mqtt.network.MqttConnection; +import javasabr.mqtt.network.message.HasMessageId; +import javasabr.mqtt.network.message.MqttMessageType; +import javasabr.rlib.common.util.StringUtils; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.experimental.Accessors; +import lombok.experimental.FieldDefaults; + +/** + * Publish received (QoS 2 delivery part 1). + */ +@Getter +@Accessors(fluent = true, chain = false) +@FieldDefaults(level = AccessLevel.PRIVATE) +public class PublishReceivedMqttInMessage extends MqttInMessage implements HasMessageId { + + private static final byte MESSAGE_TYPE = (byte) MqttMessageType.PUBLISH_RECEIVED.ordinal(); + + static { + DebugUtils.registerIncludedFields("reasonCode", "messageId"); + } + + private static final Set AVAILABLE_PROPERTIES = EnumSet.of( + /* + Followed by the UTF-8 Encoded String representing the reason associated with this response. This + Reason String is human readable, designed for diagnostics and SHOULD NOT be parsed by the + receiver. + + The sender uses this value to give additional information to the receiver. The sender MUST NOT send + this Property if it would increase the size of the PUBREL packet beyond the Maximum Packet Size + specified by the receiver [MQTT-3.6.2-2]. It is a Protocol Error to include the Reason String more than + once. + */ + PacketProperty.REASON_STRING, + /* + Followed by UTF-8 String Pair. This property can be used to provide additional diagnostic or other + information for the PUBREL. The sender MUST NOT send this property if it would increase the size of the + PUBREL packet beyond the Maximum Packet Size specified by the receiver [MQTT-3.6.2-3]. The User + Property is allowed to appear multiple times to represent multiple name, value pairs. The same name is + allowed to appear more than once + */ + PacketProperty.USER_PROPERTY); + + PublishReceivedReasonCode reasonCode; + int messageId; + + // properties + String reason; + + public PublishReceivedMqttInMessage(byte info) { + super(info); + this.reasonCode = PublishReceivedReasonCode.SUCCESS; + this.reason = StringUtils.EMPTY; + } + + @Override + protected void readVariableHeader(MqttConnection connection, ByteBuffer buffer) { + super.readVariableHeader(connection, buffer); + + // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718050 + messageId = readShortUnsigned(buffer); + + // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901143 + if (connection.isSupported(MqttVersion.MQTT_5) && buffer.hasRemaining()) { + reasonCode = PublishReceivedReasonCode.ofValue(readByteUnsigned(buffer)); + } + } + + @Override + protected boolean isPropertiesSupported(MqttConnection connection, ByteBuffer buffer) { + // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901144 + return super.isPropertiesSupported(connection, buffer) && buffer.hasRemaining(); + } + + @Override + public byte messageType() { + return MESSAGE_TYPE; + } + + @Override + protected Set availableProperties() { + return AVAILABLE_PROPERTIES; + } + + @Override + protected void applyProperty(PacketProperty property, String value) { + switch (property) { + case REASON_STRING -> reason = value; + default -> unexpectedProperty(property); + } + } +} diff --git a/network/src/main/java/javasabr/mqtt/network/message/in/PublishReleaseMqttInMessage.java b/network/src/main/java/javasabr/mqtt/network/message/in/PublishReleaseMqttInMessage.java new file mode 100644 index 00000000..792db549 --- /dev/null +++ b/network/src/main/java/javasabr/mqtt/network/message/in/PublishReleaseMqttInMessage.java @@ -0,0 +1,98 @@ +package javasabr.mqtt.network.message.in; + +import java.nio.ByteBuffer; +import java.util.EnumSet; +import java.util.Set; +import javasabr.mqtt.base.utils.DebugUtils; +import javasabr.mqtt.model.MqttVersion; +import javasabr.mqtt.model.PacketProperty; +import javasabr.mqtt.model.reason.code.PublishReleaseReasonCode; +import javasabr.mqtt.network.MqttConnection; +import javasabr.mqtt.network.message.HasMessageId; +import javasabr.mqtt.network.message.MqttMessageType; +import lombok.Getter; +import lombok.experimental.Accessors; + +/** + * Publish release (QoS 2 delivery part 2). + */ +@Getter +@Accessors(fluent = true, chain = false) +public class PublishReleaseMqttInMessage extends MqttInMessage implements HasMessageId { + + private static final byte MESSAGE_TYPE = (byte) MqttMessageType.PUBLISH_RELEASED.ordinal(); + + static { + DebugUtils.registerIncludedFields("reasonCode", "messageId"); + } + + private static final Set AVAILABLE_PROPERTIES = EnumSet.of( + /* + Followed by the UTF-8 Encoded String representing the reason associated with this response. This + Reason String is human readable, designed for diagnostics and SHOULD NOT be parsed by the + receiver. + + The sender uses this value to give additional information to the receiver. The sender MUST NOT send + this Property if it would increase the size of the PUBREL packet beyond the Maximum Packet Size + specified by the receiver [MQTT-3.6.2-2]. It is a Protocol Error to include the Reason String more than + once. + */ + PacketProperty.REASON_STRING, + /* + Followed by UTF-8 String Pair. This property can be used to provide additional diagnostic or other + information for the PUBREL. The sender MUST NOT send this property if it would increase the size of the + PUBREL packet beyond the Maximum Packet Size specified by the receiver [MQTT-3.6.2-3]. The User + Property is allowed to appear multiple times to represent multiple name, value pairs. The same name is + allowed to appear more than once + */ + PacketProperty.USER_PROPERTY); + + PublishReleaseReasonCode reasonCode; + int messageId; + + // properties + String reason; + + public PublishReleaseMqttInMessage(byte info) { + super(info); + this.reasonCode = PublishReleaseReasonCode.SUCCESS; + this.reason = ""; + } + + @Override + public byte messageType() { + return MESSAGE_TYPE; + } + + @Override + protected void readVariableHeader(MqttConnection connection, ByteBuffer buffer) { + super.readVariableHeader(connection, buffer); + + // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718055 + messageId = readShortUnsigned(buffer); + + // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901143 + if (connection.isSupported(MqttVersion.MQTT_5) && buffer.hasRemaining()) { + reasonCode = PublishReleaseReasonCode.of(readByteUnsigned(buffer)); + } + } + + @Override + protected boolean isPropertiesSupported(MqttConnection connection, ByteBuffer buffer) { + // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901143 + return super.isPropertiesSupported(connection, buffer) && buffer.hasRemaining(); + } + + @Override + protected Set availableProperties() { + return AVAILABLE_PROPERTIES; + } + + @Override + protected void applyProperty(PacketProperty property, String value) { + switch (property) { + case REASON_STRING -> reason = value; + default -> unexpectedProperty(property); + } + } +} diff --git a/network/src/main/java/javasabr/mqtt/network/message/in/SubscribeAckMqttInMessage.java b/network/src/main/java/javasabr/mqtt/network/message/in/SubscribeAckMqttInMessage.java new file mode 100644 index 00000000..0d55692a --- /dev/null +++ b/network/src/main/java/javasabr/mqtt/network/message/in/SubscribeAckMqttInMessage.java @@ -0,0 +1,102 @@ +package javasabr.mqtt.network.message.in; + +import java.nio.ByteBuffer; +import java.util.EnumSet; +import java.util.Set; +import javasabr.mqtt.model.PacketProperty; +import javasabr.mqtt.model.reason.code.SubscribeAckReasonCode; +import javasabr.mqtt.network.MqttConnection; +import javasabr.mqtt.network.message.MqttMessageType; +import javasabr.rlib.collections.array.Array; +import javasabr.rlib.collections.array.ArrayFactory; +import javasabr.rlib.collections.array.MutableArray; +import javasabr.rlib.common.util.StringUtils; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.experimental.Accessors; +import lombok.experimental.FieldDefaults; +import org.jspecify.annotations.Nullable; + +/** + * Subscribe acknowledgement. + */ +@Getter +@Accessors(fluent = true) +@FieldDefaults(level = AccessLevel.PRIVATE) +public class SubscribeAckMqttInMessage extends MqttInMessage { + + private static final byte MESSAGE_TYPE = (byte) MqttMessageType.SUBSCRIBE_ACK.ordinal(); + + private static final Set AVAILABLE_PROPERTIES = EnumSet.of( + /* + Followed by the UTF-8 Encoded String representing the reason associated with this response. This + Reason String is a human readable string designed for diagnostics and SHOULD NOT be parsed by the + Client. + + The Server uses this value to give additional information to the Client. The Server MUST NOT send this + Property if it would increase the size of the SUBACK packet beyond the Maximum Packet Size specified + by the Client + */ + PacketProperty.REASON_STRING, + /* + Followed by UTF-8 String Pair. This property can be used to provide additional diagnostic or other + information. The Server MUST NOT send this property if it would increase the size of the SUBACK packet + beyond the Maximum Packet Size specified by Client [MQTT-3.9.2-2]. The User Property is allowed to + appear multiple times to represent multiple name, value pairs. The same name is allowed to appear more + than once. + */ + PacketProperty.USER_PROPERTY); + + @Nullable + MutableArray reasonCodes; + int messageId; + + // properties + String reason; + + public SubscribeAckMqttInMessage(byte info) { + super(info); + this.reason = StringUtils.EMPTY; + } + + @Override + public byte messageType() { + return MESSAGE_TYPE; + } + + @Override + protected void readVariableHeader(MqttConnection connection, ByteBuffer buffer) { + // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718070 + messageId = readShortUnsigned(buffer); + } + + @Override + protected void readPayload(MqttConnection connection, ByteBuffer buffer) { + // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718071 + if (buffer.remaining() < 1) { + throw new IllegalStateException("No any topic filters."); + } + + reasonCodes = ArrayFactory.mutableArray(SubscribeAckReasonCode.class, buffer.remaining()); + while (buffer.hasRemaining()) { + reasonCodes.add(SubscribeAckReasonCode.of(readByteUnsigned(buffer))); + } + } + + public Array reasonCodes() { + return reasonCodes == null ? Array.empty(SubscribeAckReasonCode.class) : reasonCodes; + } + + @Override + protected Set availableProperties() { + return AVAILABLE_PROPERTIES; + } + + @Override + protected void applyProperty(PacketProperty property, String value) { + switch (property) { + case REASON_STRING -> reason = value; + default -> unexpectedProperty(property); + } + } +} diff --git a/network/src/main/java/javasabr/mqtt/network/message/in/SubscribeMqttInMessage.java b/network/src/main/java/javasabr/mqtt/network/message/in/SubscribeMqttInMessage.java new file mode 100644 index 00000000..da0599cd --- /dev/null +++ b/network/src/main/java/javasabr/mqtt/network/message/in/SubscribeMqttInMessage.java @@ -0,0 +1,122 @@ +package javasabr.mqtt.network.message.in; + +import static javasabr.mqtt.model.util.TopicUtils.buildTopicFilter; + +import java.nio.ByteBuffer; +import java.util.EnumSet; +import java.util.Set; +import javasabr.mqtt.base.utils.DebugUtils; +import javasabr.mqtt.model.MqttProperties; +import javasabr.mqtt.model.MqttVersion; +import javasabr.mqtt.model.PacketProperty; +import javasabr.mqtt.model.QoS; +import javasabr.mqtt.model.SubscribeRetainHandling; +import javasabr.mqtt.model.subscriber.SubscribeTopicFilter; +import javasabr.mqtt.network.MqttConnection; +import javasabr.mqtt.network.message.MqttMessageType; +import javasabr.rlib.collections.array.ArrayFactory; +import javasabr.rlib.collections.array.MutableArray; +import javasabr.rlib.common.util.NumberUtils; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.experimental.Accessors; +import lombok.experimental.FieldDefaults; + +/** + * Subscribe request. + */ +@Getter +@Accessors(fluent = true) +@FieldDefaults(level = AccessLevel.PRIVATE) +public class SubscribeMqttInMessage extends MqttInMessage { + + private static final byte MESSAGE_TYPE = (byte) MqttMessageType.SUBSCRIBE.ordinal(); + + static { + DebugUtils.registerIncludedFields("messageId", "topicFilters"); + } + + private static final Set AVAILABLE_PROPERTIES = EnumSet.of( + /* + Followed by a Variable Byte Integer representing the identifier of the subscription. The Subscription + Identifier can have the value of 1 to 268,435,455. It is a Protocol Error if the Subscription Identifier has a + value of 0. It is a Protocol Error to include the Subscription Identifier more than once. + + The Subscription Identifier is associated with any subscription created or modified as the result of this + SUBSCRIBE packet. If there is a Subscription Identifier, it is stored with the subscription. If this + property is + not specified, then the absence of a Subscription Identifier is stored with the subscription. + */ + PacketProperty.SUBSCRIPTION_IDENTIFIER, + /* + The User Property is allowed to appear multiple times to represent multiple name, value pairs. The same + name is allowed to appear more than once. + */ + PacketProperty.USER_PROPERTY); + + MutableArray topicFilters; + int messageId; + + // properties + int subscriptionId; + + public SubscribeMqttInMessage(byte info) { + super(info); + this.topicFilters = ArrayFactory.mutableArray(SubscribeTopicFilter.class); + this.subscriptionId = MqttProperties.SUBSCRIPTION_ID_UNDEFINED; + } + + @Override + public byte messageType() { + return MESSAGE_TYPE; + } + + @Override + protected void readVariableHeader(MqttConnection connection, ByteBuffer buffer) { + // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718065 + messageId = readShortUnsigned(buffer); + } + + @Override + protected void readPayload(MqttConnection connection, ByteBuffer buffer) { + + if (buffer.remaining() < 1) { + throw new IllegalStateException("No any topic filters."); + } + + boolean isMqtt5 = connection.isSupported(MqttVersion.MQTT_5); + + // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718066 + // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901168 + while (buffer.hasRemaining()) { + + String topicFilter = readString(buffer, Integer.MAX_VALUE); + int options = readByteUnsigned(buffer); + + QoS qos = QoS.of(options & 0x03); + SubscribeRetainHandling retainHandling = isMqtt5 ? SubscribeRetainHandling.of((options >> 4) & 0x03) : SubscribeRetainHandling.SEND; + + if (qos == QoS.INVALID || retainHandling == SubscribeRetainHandling.INVALID) { + throw new IllegalStateException("Unsupported qos or retain handling"); + } + + boolean noLocal = !isMqtt5 || NumberUtils.isSetBit(options, 2); + boolean rap = !isMqtt5 || NumberUtils.isSetBit(options, 3); + + topicFilters.add(new SubscribeTopicFilter(buildTopicFilter(topicFilter), qos, retainHandling, noLocal, rap)); + } + } + + @Override + protected Set availableProperties() { + return AVAILABLE_PROPERTIES; + } + + @Override + protected void applyProperty(PacketProperty property, long value) { + switch (property) { + case SUBSCRIPTION_IDENTIFIER -> subscriptionId = (int) value; + default -> unexpectedProperty(property); + } + } +} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/in/UnsubscribeAckInPacket.java b/network/src/main/java/javasabr/mqtt/network/message/in/UnsubscribeAckMqttInMessage.java similarity index 83% rename from network/src/main/java/javasabr/mqtt/network/packet/in/UnsubscribeAckInPacket.java rename to network/src/main/java/javasabr/mqtt/network/message/in/UnsubscribeAckMqttInMessage.java index 8bb82936..91b38a87 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/in/UnsubscribeAckInPacket.java +++ b/network/src/main/java/javasabr/mqtt/network/message/in/UnsubscribeAckMqttInMessage.java @@ -1,4 +1,4 @@ -package javasabr.mqtt.network.packet.in; +package javasabr.mqtt.network.message.in; import java.nio.ByteBuffer; import java.util.EnumSet; @@ -7,7 +7,7 @@ import javasabr.mqtt.model.PacketProperty; import javasabr.mqtt.model.reason.code.UnsubscribeAckReasonCode; import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.MqttPacketType; +import javasabr.mqtt.network.message.MqttMessageType; import javasabr.rlib.collections.array.Array; import javasabr.rlib.collections.array.ArrayFactory; import javasabr.rlib.collections.array.MutableArray; @@ -24,9 +24,9 @@ @Getter @Accessors(fluent = true, chain = false) @FieldDefaults(level = AccessLevel.PRIVATE) -public class UnsubscribeAckInPacket extends MqttReadablePacket { +public class UnsubscribeAckMqttInMessage extends MqttInMessage { - private static final byte PACKET_TYPE = (byte) MqttPacketType.UNSUBSCRIBE_ACK.ordinal(); + private static final byte MESSAGE_TYPE = (byte) MqttMessageType.UNSUBSCRIBE_ACK.ordinal(); private static final Set AVAILABLE_PROPERTIES = EnumSet.of( /* @@ -53,24 +53,24 @@ public class UnsubscribeAckInPacket extends MqttReadablePacket { @Nullable MutableArray reasonCodes; - int packetId; + int messageId; // properties String reason = StringUtils.EMPTY; - public UnsubscribeAckInPacket(byte info) { + public UnsubscribeAckMqttInMessage(byte info) { super(info); } @Override - public byte packetType() { - return PACKET_TYPE; + public byte messageType() { + return MESSAGE_TYPE; } @Override protected void readVariableHeader(MqttConnection connection, ByteBuffer buffer) { // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718079 - packetId = readShortUnsigned(buffer); + messageId = readShortUnsigned(buffer); } @Override @@ -79,21 +79,18 @@ protected void readPayload(MqttConnection connection, ByteBuffer buffer) { // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901194 if (!connection.isSupported(MqttVersion.MQTT_5)) { return; - } - - if (!buffer.hasRemaining()) { + } else if (!buffer.hasRemaining()) { return; } reasonCodes = ArrayFactory.mutableArray(UnsubscribeAckReasonCode.class, buffer.remaining()); - while (buffer.hasRemaining()) { reasonCodes.add(UnsubscribeAckReasonCode.of(readByteUnsigned(buffer))); } } @Override - protected Set getAvailableProperties() { + protected Set availableProperties() { return AVAILABLE_PROPERTIES; } @@ -104,13 +101,8 @@ public Array reasonCodes() { @Override protected void applyProperty(PacketProperty property, String value) { switch (property) { - case REASON_STRING: { - reason = value; - break; - } - default: { - unexpectedProperty(property); - } + case REASON_STRING -> reason = value; + default -> unexpectedProperty(property); } } } diff --git a/network/src/main/java/javasabr/mqtt/network/packet/in/UnsubscribeInPacket.java b/network/src/main/java/javasabr/mqtt/network/message/in/UnsubscribeMqttInMessage.java similarity index 50% rename from network/src/main/java/javasabr/mqtt/network/packet/in/UnsubscribeInPacket.java rename to network/src/main/java/javasabr/mqtt/network/message/in/UnsubscribeMqttInMessage.java index 455b0603..abc3b179 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/in/UnsubscribeInPacket.java +++ b/network/src/main/java/javasabr/mqtt/network/message/in/UnsubscribeMqttInMessage.java @@ -1,6 +1,6 @@ -package javasabr.mqtt.network.packet.in; +package javasabr.mqtt.network.message.in; -import static javasabr.mqtt.model.utils.TopicUtils.buildTopicFilter; +import static javasabr.mqtt.model.util.TopicUtils.buildTopicFilter; import java.nio.ByteBuffer; import java.util.EnumSet; @@ -8,58 +8,62 @@ import javasabr.mqtt.model.PacketProperty; import javasabr.mqtt.model.topic.TopicFilter; import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.MqttPacketType; +import javasabr.mqtt.network.message.MqttMessageType; import javasabr.rlib.collections.array.ArrayFactory; import javasabr.rlib.collections.array.MutableArray; +import lombok.AccessLevel; import lombok.Getter; +import lombok.experimental.Accessors; +import lombok.experimental.FieldDefaults; /** * Unsubscribe request. */ @Getter -public class UnsubscribeInPacket extends MqttReadablePacket { +@Accessors(fluent = true) +@FieldDefaults(level = AccessLevel.PRIVATE) +public class UnsubscribeMqttInMessage extends MqttInMessage { - private static final byte PACKET_TYPE = (byte) MqttPacketType.UNSUBSCRIBE.ordinal(); + private static final byte MESSAGE_TYPE = (byte) MqttMessageType.UNSUBSCRIBE.ordinal(); private static final Set AVAILABLE_PROPERTIES = EnumSet.of( - /* - The User Property is allowed to appear multiple times to represent multiple name, value pairs. The same - name is allowed to appear more than once. - */ + /* + The User Property is allowed to appear multiple times to represent multiple name, value pairs. The same + name is allowed to appear more than once. + */ PacketProperty.USER_PROPERTY); - private MutableArray topicFilters; - private int packetId; + MutableArray topicFilters; + int messageId; - public UnsubscribeInPacket(byte info) { + public UnsubscribeMqttInMessage(byte info) { super(info); - this.topicFilters = ArrayFactory.mutableArray(TopicFilter.class); } @Override - public byte packetType() { - return PACKET_TYPE; + public byte messageType() { + return MESSAGE_TYPE; } @Override protected void readVariableHeader(MqttConnection connection, ByteBuffer buffer) { - packetId = readShortUnsigned(buffer); + messageId = readShortUnsigned(buffer); } @Override protected void readPayload(MqttConnection connection, ByteBuffer buffer) { - if (buffer.remaining() < 1) { throw new IllegalStateException("No any topic filters."); } + topicFilters = ArrayFactory.mutableArray(TopicFilter.class); while (buffer.hasRemaining()) { topicFilters.add(buildTopicFilter(readString(buffer, Integer.MAX_VALUE))); } } @Override - protected Set getAvailableProperties() { + protected Set availableProperties() { return AVAILABLE_PROPERTIES; } } diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/package-info.java b/network/src/main/java/javasabr/mqtt/network/message/in/package-info.java similarity index 57% rename from network/src/main/java/javasabr/mqtt/network/packet/out/package-info.java rename to network/src/main/java/javasabr/mqtt/network/message/in/package-info.java index aa1207b6..dd51c4bb 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/package-info.java +++ b/network/src/main/java/javasabr/mqtt/network/message/in/package-info.java @@ -1,4 +1,4 @@ @NullMarked -package javasabr.mqtt.network.packet.out; +package javasabr.mqtt.network.message.in; import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/Authentication5OutPacket.java b/network/src/main/java/javasabr/mqtt/network/message/out/AuthenticationMqtt5OutMessage.java similarity index 84% rename from network/src/main/java/javasabr/mqtt/network/packet/out/Authentication5OutPacket.java rename to network/src/main/java/javasabr/mqtt/network/message/out/AuthenticationMqtt5OutMessage.java index 4429803b..055cc39e 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/Authentication5OutPacket.java +++ b/network/src/main/java/javasabr/mqtt/network/message/out/AuthenticationMqtt5OutMessage.java @@ -1,4 +1,4 @@ -package javasabr.mqtt.network.packet.out; +package javasabr.mqtt.network.message.out; import java.nio.ByteBuffer; import java.util.EnumSet; @@ -7,17 +7,20 @@ import javasabr.mqtt.model.data.type.StringPair; import javasabr.mqtt.model.reason.code.AuthenticateReasonCode; import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.MqttPacketType; +import javasabr.mqtt.network.message.MqttMessageType; import javasabr.rlib.collections.array.Array; +import lombok.AccessLevel; import lombok.RequiredArgsConstructor; +import lombok.experimental.FieldDefaults; /** * Authentication exchange. */ @RequiredArgsConstructor -public class Authentication5OutPacket extends MqttWritablePacket { +@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) +public class AuthenticationMqtt5OutMessage extends MqttOutMessage { - private static final byte PACKET_TYPE = (byte) MqttPacketType.AUTHENTICATE.ordinal(); + private static final byte MESSAGE_TYPE = (byte) MqttMessageType.AUTHENTICATE.ordinal(); private static final Set AVAILABLE_PROPERTIES = EnumSet.of( /* @@ -50,18 +53,18 @@ public class Authentication5OutPacket extends MqttWritablePacket { */ PacketProperty.USER_PROPERTY); - private final Array userProperties; + Array userProperties; - private final AuthenticateReasonCode reasonCode; + AuthenticateReasonCode reasonCode; - private final String reason; - private final String authenticateMethod; + String reason; + String authenticateMethod; - private final byte[] authenticateData; + byte[] authenticateData; @Override - protected byte packetType() { - return PACKET_TYPE; + protected byte messageType() { + return MESSAGE_TYPE; } @Override @@ -77,7 +80,6 @@ protected boolean isPropertiesSupported(MqttConnection connection) { @Override protected void writeProperties(MqttConnection connection, ByteBuffer buffer) { - // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901221 writeStringPairProperties(buffer, PacketProperty.USER_PROPERTY, userProperties); writeNotEmptyProperty(buffer, PacketProperty.REASON_STRING, reason); diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/ConnectAck311OutPacket.java b/network/src/main/java/javasabr/mqtt/network/message/out/ConnectAckMqtt311OutMessage.java similarity index 85% rename from network/src/main/java/javasabr/mqtt/network/packet/out/ConnectAck311OutPacket.java rename to network/src/main/java/javasabr/mqtt/network/message/out/ConnectAckMqtt311OutMessage.java index 631fe6cc..c756da62 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/ConnectAck311OutPacket.java +++ b/network/src/main/java/javasabr/mqtt/network/message/out/ConnectAckMqtt311OutMessage.java @@ -1,10 +1,10 @@ -package javasabr.mqtt.network.packet.out; +package javasabr.mqtt.network.message.out; import java.nio.ByteBuffer; import javasabr.mqtt.base.utils.DebugUtils; import javasabr.mqtt.model.reason.code.ConnectAckReasonCode; import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.MqttPacketType; +import javasabr.mqtt.network.message.MqttMessageType; import lombok.AccessLevel; import lombok.RequiredArgsConstructor; import lombok.experimental.FieldDefaults; @@ -14,9 +14,9 @@ */ @RequiredArgsConstructor @FieldDefaults(level = AccessLevel.PROTECTED, makeFinal = true) -public class ConnectAck311OutPacket extends MqttWritablePacket { +public class ConnectAckMqtt311OutMessage extends MqttOutMessage { - private static final byte PACKET_TYPE = (byte) MqttPacketType.CONNECT_ACK.ordinal(); + private static final byte MESSAGE_TYPE = (byte) MqttMessageType.CONNECT_ACK.ordinal(); static { DebugUtils.registerIncludedFields("reasonCode", "sessionPresent"); @@ -39,8 +39,8 @@ public class ConnectAck311OutPacket extends MqttWritablePacket { boolean sessionPresent; @Override - protected byte packetType() { - return PACKET_TYPE; + protected byte messageType() { + return MESSAGE_TYPE; } @Override diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/ConnectAck5OutPacket.java b/network/src/main/java/javasabr/mqtt/network/message/out/ConnectAckMqtt5OutMessage.java similarity index 99% rename from network/src/main/java/javasabr/mqtt/network/packet/out/ConnectAck5OutPacket.java rename to network/src/main/java/javasabr/mqtt/network/message/out/ConnectAckMqtt5OutMessage.java index 034b1003..cc3d2cd6 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/ConnectAck5OutPacket.java +++ b/network/src/main/java/javasabr/mqtt/network/message/out/ConnectAckMqtt5OutMessage.java @@ -1,4 +1,4 @@ -package javasabr.mqtt.network.packet.out; +package javasabr.mqtt.network.message.out; import java.nio.ByteBuffer; import java.util.EnumSet; @@ -18,7 +18,7 @@ * Connect acknowledgment. */ @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) -public class ConnectAck5OutPacket extends ConnectAck311OutPacket { +public class ConnectAckMqtt5OutMessage extends ConnectAckMqtt311OutMessage { static { DebugUtils.registerIncludedFields("reasonCode", "sessionPresent", "clientId"); @@ -246,7 +246,7 @@ public class ConnectAck5OutPacket extends ConnectAck311OutPacket { Array userProperties; - public ConnectAck5OutPacket( + public ConnectAckMqtt5OutMessage( MqttClientConnectionConfig connectionConfig, ConnectAckReasonCode reasonCode, boolean sessionPresent, diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/Connect311OutPacket.java b/network/src/main/java/javasabr/mqtt/network/message/out/ConnectMqtt311OutMessage.java similarity index 71% rename from network/src/main/java/javasabr/mqtt/network/packet/out/Connect311OutPacket.java rename to network/src/main/java/javasabr/mqtt/network/message/out/ConnectMqtt311OutMessage.java index 144f8a1d..efdacba8 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/Connect311OutPacket.java +++ b/network/src/main/java/javasabr/mqtt/network/message/out/ConnectMqtt311OutMessage.java @@ -1,37 +1,40 @@ -package javasabr.mqtt.network.packet.out; +package javasabr.mqtt.network.message.out; import java.nio.ByteBuffer; import javasabr.mqtt.model.MqttVersion; import javasabr.mqtt.model.QoS; import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.MqttPacketType; +import javasabr.mqtt.network.message.MqttMessageType; import javasabr.rlib.common.util.ArrayUtils; import javasabr.rlib.common.util.StringUtils; +import lombok.AccessLevel; import lombok.RequiredArgsConstructor; +import lombok.experimental.FieldDefaults; /** * Connect request. */ @RequiredArgsConstructor -public class Connect311OutPacket extends MqttWritablePacket { +@FieldDefaults(level = AccessLevel.PROTECTED, makeFinal = true) +public class ConnectMqtt311OutMessage extends MqttOutMessage { - private static final byte PACKET_TYPE = (byte) MqttPacketType.CONNECT.ordinal(); + private static final byte MESSAGE_TYPE = (byte) MqttMessageType.CONNECT.ordinal(); - private final String username; - private final String willTopic; - private final String clientId; + String username; + String willTopic; + String clientId; - private final byte[] password; - private final byte[] willPayload; + byte[] password; + byte[] willPayload; - private final QoS willQos; + QoS willQos; - private final int keepAlive; + int keepAlive; - private final boolean willRetain; - private final boolean cleanStart; + boolean willRetain; + boolean cleanStart; - public Connect311OutPacket(String clientId, int keepAlive) { + public ConnectMqtt311OutMessage(String clientId, int keepAlive) { this( StringUtils.EMPTY, StringUtils.EMPTY, @@ -44,20 +47,18 @@ public Connect311OutPacket(String clientId, int keepAlive) { false); } - protected MqttVersion getMqttVersion() { + protected MqttVersion mqttVersion() { return MqttVersion.MQTT_3_1_1; } @Override - protected byte packetType() { - return PACKET_TYPE; + protected byte messageType() { + return MESSAGE_TYPE; } @Override protected void writeVariableHeader(MqttConnection connection, ByteBuffer buffer) { - - MqttVersion mqttVersion = getMqttVersion(); - + MqttVersion mqttVersion = mqttVersion(); // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718030 writeString(buffer, mqttVersion.rawName()); writeByte(buffer, mqttVersion.version()); @@ -113,6 +114,5 @@ private int buildConnectFlags() { return connectFlags; } - protected void appendWillProperties(ByteBuffer buffer) { - } + protected void appendWillProperties(ByteBuffer buffer) {} } diff --git a/network/src/main/java/javasabr/mqtt/network/message/out/ConnectMqtt5OutMessage.java b/network/src/main/java/javasabr/mqtt/network/message/out/ConnectMqtt5OutMessage.java new file mode 100644 index 00000000..471198ff --- /dev/null +++ b/network/src/main/java/javasabr/mqtt/network/message/out/ConnectMqtt5OutMessage.java @@ -0,0 +1,304 @@ +package javasabr.mqtt.network.message.out; + +import java.nio.ByteBuffer; +import java.util.EnumSet; +import java.util.Set; +import javasabr.mqtt.model.MqttProperties; +import javasabr.mqtt.model.MqttVersion; +import javasabr.mqtt.model.PacketProperty; +import javasabr.mqtt.model.QoS; +import javasabr.mqtt.model.data.type.StringPair; +import javasabr.mqtt.network.MqttConnection; +import javasabr.mqtt.network.util.MqttDataUtils; +import javasabr.rlib.collections.array.Array; +import javasabr.rlib.common.util.ArrayUtils; +import javasabr.rlib.common.util.StringUtils; +import lombok.AccessLevel; +import lombok.experimental.FieldDefaults; + +/** + * Connect request. + */ +@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) +public class ConnectMqtt5OutMessage extends ConnectMqtt311OutMessage { + + private static final Set AVAILABLE_PROPERTIES = EnumSet.of( + /* + If the Session Expiry Interval is absent the value 0 is used. If it is set to 0, + or is absent, the Session ends when the Network Connection is closed. + If the Session Expiry Interval is 0xFFFFFFFF (UINT_MAX), the Session does not expire. + + The Client and Server MUST store the Session State after the Network Connection is closed if the + Session Expiry Interval is greater than 0 + */ + PacketProperty.SESSION_EXPIRY_INTERVAL, + /* + Followed by the Two Byte Integer representing the Receive Maximum value. It is a Protocol Error to + include the Receive Maximum value more than once or for it to have the value 0. + + The Client uses this value to limit the number of QoS 1 and QoS 2 publications that it is willing to process + concurrently. There is no mechanism to limit the QoS 0 publications that the Server might try to send. + + The value of Receive Maximum applies only to the current Network Connection. If the Receive Maximum + value is absent then its value defaults to 65,535. + */ + PacketProperty.RECEIVE_MAXIMUM_PUBLISH, + /* + Followed by a Four Byte Integer representing the Maximum Packet Size the Client is willing to accept. If + the Maximum Packet Size is not present, no limit on the packet size is imposed beyond the limitations in + the protocol as a result of the remaining length encoding and the protocol header sizes. + + It is a Protocol Error to include the Maximum Packet Size more than once, or for the value to be set to + zero. + */ + PacketProperty.MAXIMUM_PACKET_SIZE, + /* + Followed by the Two Byte Integer representing the Topic Alias Maximum value. It is a Protocol Error to + include the Topic Alias Maximum value more than once. If the Topic Alias Maximum property is absent, + the default value is 0. + + This value indicates the highest value that the Client will accept as a Topic Alias sent by the Server. The + Client uses this value to limit the number of Topic Aliases that it is willing to hold on this Connection. The + Server MUST NOT send a Topic Alias in a PUBLISH packet to the Client greater than Topic Alias + Maximum [MQTT-3.1.2-26]. A value of 0 indicates that the Client does not accept any Topic Aliases on + this connection. If Topic Alias Maximum is absent or zero, the Server MUST NOT send any Topic Aliases + to the Client [MQTT-3.1.2-27]. + */ + PacketProperty.TOPIC_ALIAS_MAXIMUM, + /* + Followed by a Byte with a value of either 0 or 1. It is Protocol Error to include the Request Response + Information more than once, or to have a value other than 0 or 1. If the Request Response Information is + absent, the value of 0 is used. + + The Client uses this value to request the Server to return Response Information in the CONNACK. A + value of 0 indicates that the Server MUST NOT return Response Information [MQTT-3.1.2-28]. If the + value is 1 the Server MAY return Response Information in the CONNACK packet. + */ + PacketProperty.REQUEST_RESPONSE_INFORMATION, + /* + Followed by a Byte with a value of either 0 or 1. It is a Protocol Error to include Request Problem + Information more than once, or to have a value other than 0 or 1. If the Request Problem Information is + 8absent, the value of 1 is used. + + The Client uses this value to indicate whether the Reason String or User Properties are sent in the case + of failures. + + If the value of Request Problem Information is 0, the Server MAY return a Reason String or User + Properties on a CONNACK or DISCONNECT packet, but MUST NOT send a Reason String or User + Properties on any packet other than PUBLISH, CONNACK, or DISCONNECT [MQTT-3.1.2-29]. If the + value is 0 and the Client receives a Reason String or User Properties in a packet other than PUBLISH, + CONNACK, or DISCONNECT, it uses a DISCONNECT packet with Reason Code 0x82 (Protocol Error) + as described in section 4.13 Handling errors. + + If this value is 1, the Server MAY return a Reason String or User Properties on any packet where it is + allowed. + */ + PacketProperty.REQUEST_PROBLEM_INFORMATION, + /* + The User Property is allowed to appear multiple times to represent multiple name, value pairs. The same + name is allowed to appear more than once + */ + PacketProperty.USER_PROPERTY, + /* + Followed by a UTF-8 Encoded String containing the name of the authentication method used for + extended authentication .It is a Protocol Error to include Authentication Method more than once. + If Authentication Method is absent, extended authentication is not performed. Refer to section 4.12. + + If a Client sets an Authentication Method in the CONNECT, the Client MUST NOT send any packets other + than AUTH or DISCONNECT packets until it has received a CONNACK packet + */ + PacketProperty.AUTHENTICATION_METHOD, + /* + Followed by Binary Data containing authentication data. It is a Protocol Error to include Authentication + Data if there is no Authentication Method. It is a Protocol Error to include Authentication Data more than + once. + + The contents of this data are defined by the authentication method. Refer to section 4.12 for more + information about extended authentication. + */ + PacketProperty.AUTHENTICATION_DATA); + + private static final Set WILL_PROPERTIES = EnumSet.of( + /* + Followed by the Four Byte Integer representing the Will Delay Interval in seconds. It is a Protocol Error to + include the Will Delay Interval more than once. If the Will Delay Interval is absent, the default value is 0 + and there is no delay before the Will Message is published. + + The Server delays publishing the Client’s Will Message until the Will Delay Interval has passed or the + Session ends, whichever happens first. If a new Network Connection to this Session is made before the + Will Delay Interval has passed, the Server MUST NOT send the Will Message + */ + PacketProperty.WILL_DELAY_INTERVAL, + /* + Followed by the value of the Payload Format Indicator, either of: + • 0 (0x00) Byte Indicates that the Will Message is unspecified bytes, which is equivalent to not + sending a Payload Format Indicator. + • 1 (0x01) Byte Indicates that the Will Message is UTF-8 Encoded Character Data. The UTF-8 data + in the Payload MUST be well-formed UTF-8 as defined by the Unicode specification + [Unicode] and restated in RFC 3629 [RFC3629]. + + It is a Protocol Error to include the Payload Format Indicator more than once. The Server MAY validate + that the Will Message is of the format indicated, and if it is not se + */ + PacketProperty.PAYLOAD_FORMAT_INDICATOR, + /* + Followed by the Four Byte Integer representing the Message Expiry Interval. It is a Protocol Error to + include the Message Expiry Interval more than once. + + If present, the Four Byte value is the lifetime of the Will Message in seconds and is sent as the + Publication Expiry Interval when the Server publishes the Will Message. + + If absent, no Message Expiry Interval is sent when the Server publishes the Will Message. + */ + PacketProperty.MESSAGE_EXPIRY_INTERVAL, + /* + Followed by a UTF-8 Encoded String describing the content of the Will Message. It is a Protocol Error to + include the Content Type more than once. The value of the Content Type is defined by the sending and + receiving application. + */ + PacketProperty.CONTENT_TYPE, + /* + Followed by a UTF-8 Encoded String which is used as the Topic Name for a response message. It is a + Protocol Error to include the Response Topic more than once. The presence of a Response Topic + identifies the Will Message as a Request. + */ + PacketProperty.RESPONSE_TOPIC, + /* + Followed by Binary Data. The Correlation Data is used by the sender of the Request Message to identify + which request the Response Message is for when it is received. It is a Protocol Error to include + Correlation Data more than once. If the Correlation Data is not present, the Requester does not require + any correlation data. + + The value of the Correlation Data only has meaning to the sender of the Request Message and receiver + of the Response Message. + */ + PacketProperty.CORRELATION_DATA, + /* + Followed by a UTF-8 String Pair. The User Property is allowed to appear multiple times to represent + multiple name, value pairs. The same name is allowed to appear more than once. + + The Server MUST maintain the order of User Properties when publishing the Will Message + */ + PacketProperty.USER_PROPERTY); + + // properties + Array userProperties; + String authenticationMethod; + byte[] authenticationData; + + long sessionExpiryInterval; + int receiveMax; + int maximumPacketSize; + int topicAliasMaximum; + boolean requestResponseInformation; + boolean requestProblemInformation; + + public ConnectMqtt5OutMessage(String clientId, int keepAlive) { + this( + StringUtils.EMPTY, + StringUtils.EMPTY, + clientId, + ArrayUtils.EMPTY_BYTE_ARRAY, + ArrayUtils.EMPTY_BYTE_ARRAY, + QoS.AT_MOST_ONCE, + keepAlive, + false, + false, + Array.empty(StringPair.class), + StringUtils.EMPTY, + ArrayUtils.EMPTY_BYTE_ARRAY, + MqttProperties.SESSION_EXPIRY_INTERVAL_UNDEFINED, + MqttProperties.RECEIVE_MAXIMUM_UNDEFINED, + MqttProperties.MAXIMUM_PACKET_SIZE_UNDEFINED, + MqttProperties.TOPIC_ALIAS_MAXIMUM_UNDEFINED, + false, + false); + } + + public ConnectMqtt5OutMessage( + String username, + String willTopic, + String clientId, + byte[] password, + byte[] willPayload, + QoS willQos, + int keepAlive, + boolean willRetain, + boolean cleanStart, + Array userProperties, + String authenticationMethod, + byte[] authenticationData, + long sessionExpiryInterval, + int receiveMax, + int maximumPacketSize, + int topicAliasMaximum, + boolean requestResponseInformation, + boolean requestProblemInformation) { + super(username, willTopic, clientId, password, willPayload, willQos, keepAlive, willRetain, cleanStart); + this.userProperties = userProperties; + this.authenticationMethod = authenticationMethod; + this.authenticationData = authenticationData; + this.sessionExpiryInterval = sessionExpiryInterval; + this.receiveMax = receiveMax; + this.maximumPacketSize = maximumPacketSize; + this.topicAliasMaximum = topicAliasMaximum; + this.requestResponseInformation = requestResponseInformation; + this.requestProblemInformation = requestProblemInformation; + } + + protected MqttVersion mqttVersion() { + return MqttVersion.MQTT_5; + } + + @Override + protected boolean isPropertiesSupported(MqttConnection connection) { + return true; + } + + @Override + protected void appendWillProperties(ByteBuffer buffer) { + + var propertiesBuffer = propertiesBuffer(); + + writeWillProperties(propertiesBuffer); + + if (propertiesBuffer.position() < 1) { + buffer.put((byte) 0); + return; + } + + propertiesBuffer.flip(); + + MqttDataUtils + .writeMbi(propertiesBuffer.limit(), buffer) + .put(propertiesBuffer); + } + + @Override + protected void writeProperties(MqttConnection connection, ByteBuffer buffer) { + // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901046 + writeStringPairProperties(buffer, PacketProperty.USER_PROPERTY, userProperties); + writeNotEmptyProperty(buffer, PacketProperty.AUTHENTICATION_METHOD, authenticationMethod); + writeNotEmptyProperty(buffer, PacketProperty.AUTHENTICATION_DATA, authenticationData); + writeProperty(buffer, PacketProperty.REQUEST_RESPONSE_INFORMATION, requestResponseInformation, false); + writeProperty(buffer, PacketProperty.REQUEST_PROBLEM_INFORMATION, requestProblemInformation, false); + writeProperty(buffer, PacketProperty.RECEIVE_MAXIMUM_PUBLISH, receiveMax, MqttProperties.RECEIVE_MAXIMUM_UNDEFINED); + writeProperty( + buffer, + PacketProperty.TOPIC_ALIAS_MAXIMUM, + topicAliasMaximum, + MqttProperties.TOPIC_ALIAS_MAXIMUM_UNDEFINED); + writeProperty( + buffer, + PacketProperty.SESSION_EXPIRY_INTERVAL, + sessionExpiryInterval, + MqttProperties.SESSION_EXPIRY_INTERVAL_UNDEFINED); + writeProperty( + buffer, + PacketProperty.MAXIMUM_PACKET_SIZE, + maximumPacketSize, + MqttProperties.MAXIMUM_PACKET_SIZE_UNDEFINED); + } + + protected void writeWillProperties(ByteBuffer buffer) {} +} diff --git a/network/src/main/java/javasabr/mqtt/network/message/out/DisconnectMqtt311OutMessage.java b/network/src/main/java/javasabr/mqtt/network/message/out/DisconnectMqtt311OutMessage.java new file mode 100644 index 00000000..4d7393f6 --- /dev/null +++ b/network/src/main/java/javasabr/mqtt/network/message/out/DisconnectMqtt311OutMessage.java @@ -0,0 +1,22 @@ +package javasabr.mqtt.network.message.out; + +import javasabr.mqtt.network.MqttConnection; +import javasabr.mqtt.network.message.MqttMessageType; + +/** + * Disconnect notification. + */ +public class DisconnectMqtt311OutMessage extends MqttOutMessage { + + private static final byte MESSAGE_TYPE = (byte) MqttMessageType.DISCONNECT.ordinal(); + + @Override + public int expectedLength(MqttConnection connection) { + return 0; + } + + @Override + protected byte messageType() { + return MESSAGE_TYPE; + } +} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/Disconnect5OutPacket.java b/network/src/main/java/javasabr/mqtt/network/message/out/DisconnectMqtt5OutMessage.java similarity index 89% rename from network/src/main/java/javasabr/mqtt/network/packet/out/Disconnect5OutPacket.java rename to network/src/main/java/javasabr/mqtt/network/message/out/DisconnectMqtt5OutMessage.java index 7b801d33..cecfccb7 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/Disconnect5OutPacket.java +++ b/network/src/main/java/javasabr/mqtt/network/message/out/DisconnectMqtt5OutMessage.java @@ -1,4 +1,4 @@ -package javasabr.mqtt.network.packet.out; +package javasabr.mqtt.network.message.out; import java.nio.ByteBuffer; import java.util.EnumSet; @@ -9,13 +9,16 @@ import javasabr.mqtt.model.reason.code.DisconnectReasonCode; import javasabr.mqtt.network.MqttConnection; import javasabr.rlib.collections.array.Array; +import lombok.AccessLevel; import lombok.RequiredArgsConstructor; +import lombok.experimental.FieldDefaults; /** * Disconnect notification. */ @RequiredArgsConstructor -public class Disconnect5OutPacket extends Disconnect311OutPacket { +@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) +public class DisconnectMqtt5OutMessage extends DisconnectMqtt311OutMessage { private static final Set AVAILABLE_PROPERTIES = EnumSet.of( /* @@ -49,13 +52,13 @@ public class Disconnect5OutPacket extends Disconnect311OutPacket { */ PacketProperty.SERVER_REFERENCE); - private final DisconnectReasonCode reasonCode; - private final Array userProperties; + DisconnectReasonCode reasonCode; + Array userProperties; - private final String reason; - private final String serverReference; + String reason; + String serverReference; - private final long sessionExpiryInterval; + long sessionExpiryInterval; @Override protected void writeVariableHeader(MqttConnection connection, ByteBuffer buffer) { @@ -70,7 +73,6 @@ protected boolean isPropertiesSupported(MqttConnection connection) { @Override protected void writeProperties(MqttConnection connection, ByteBuffer buffer) { - // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901209 writeStringPairProperties(buffer, PacketProperty.USER_PROPERTY, userProperties); writeNotEmptyProperty(buffer, PacketProperty.REASON_STRING, reason); diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/MqttWritablePacket.java b/network/src/main/java/javasabr/mqtt/network/message/out/MqttOutMessage.java similarity index 87% rename from network/src/main/java/javasabr/mqtt/network/packet/out/MqttWritablePacket.java rename to network/src/main/java/javasabr/mqtt/network/message/out/MqttOutMessage.java index 726510cd..ef34f7a8 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/MqttWritablePacket.java +++ b/network/src/main/java/javasabr/mqtt/network/message/out/MqttOutMessage.java @@ -1,4 +1,4 @@ -package javasabr.mqtt.network.packet.out; +package javasabr.mqtt.network.message.out; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; @@ -6,14 +6,14 @@ import javasabr.mqtt.model.PacketProperty; import javasabr.mqtt.model.data.type.StringPair; import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.utils.MqttDataUtils; +import javasabr.mqtt.network.util.MqttDataUtils; import javasabr.rlib.collections.array.Array; import javasabr.rlib.common.util.NumberUtils; import javasabr.rlib.network.packet.impl.AbstractWritableNetworkPacket; import lombok.RequiredArgsConstructor; @RequiredArgsConstructor -public abstract class MqttWritablePacket extends AbstractWritableNetworkPacket { +public abstract class MqttOutMessage extends AbstractWritableNetworkPacket { private static final ThreadLocal LOCAL_BUFFER = ThreadLocal.withInitial(() -> ByteBuffer.allocate( 1024 * 1024)); @@ -42,12 +42,12 @@ protected boolean isPropertiesSupported(MqttConnection connection) { protected void writeProperties(MqttConnection connection, ByteBuffer buffer) {} public final int packetTypeAndFlags() { - byte type = packetType(); + byte type = messageType(); byte controlFlags = packetFlags(); return NumberUtils.setHighByteBits(controlFlags, type); } - protected byte packetType() { + protected byte messageType() { throw new UnsupportedOperationException(); } @@ -94,25 +94,11 @@ public void writeProperty(ByteBuffer buffer, PacketProperty property, long value public void writeProperty(ByteBuffer buffer, PacketProperty property, long value) { buffer.put(property.id()); switch (property.dataType()) { - case BYTE: { - writeByte(buffer, (int) value); - break; - } - case SHORT: { - writeShort(buffer, (int) value); - break; - } - case INTEGER: { - writeInt(buffer, (int) value); - break; - } - case MULTI_BYTE_INTEGER: { - writeMbi(buffer, (int) value); - break; - } - default: { - throw new IllegalArgumentException("Incorrect property type: " + property); - } + case BYTE -> writeByte(buffer, (int) value); + case SHORT -> writeShort(buffer, (int) value); + case INTEGER -> writeInt(buffer, (int) value); + case MULTI_BYTE_INTEGER -> writeMbi(buffer, (int) value); + default -> throw new IllegalArgumentException("Incorrect property type: " + property); } } diff --git a/network/src/main/java/javasabr/mqtt/network/message/out/PingRequestMqtt311OutMessage.java b/network/src/main/java/javasabr/mqtt/network/message/out/PingRequestMqtt311OutMessage.java new file mode 100644 index 00000000..db8d6ce0 --- /dev/null +++ b/network/src/main/java/javasabr/mqtt/network/message/out/PingRequestMqtt311OutMessage.java @@ -0,0 +1,16 @@ +package javasabr.mqtt.network.message.out; + +import javasabr.mqtt.network.message.MqttMessageType; + +/** + * PING request. + */ +public class PingRequestMqtt311OutMessage extends MqttOutMessage { + + private static final byte MESSAGE_TYPE = (byte) MqttMessageType.PING_REQUEST.ordinal(); + + @Override + protected byte messageType() { + return MESSAGE_TYPE; + } +} diff --git a/network/src/main/java/javasabr/mqtt/network/message/out/PingResponseMqtt311OutMessage.java b/network/src/main/java/javasabr/mqtt/network/message/out/PingResponseMqtt311OutMessage.java new file mode 100644 index 00000000..ea92d9c6 --- /dev/null +++ b/network/src/main/java/javasabr/mqtt/network/message/out/PingResponseMqtt311OutMessage.java @@ -0,0 +1,16 @@ +package javasabr.mqtt.network.message.out; + +import javasabr.mqtt.network.message.MqttMessageType; + +/** + * PING response. + */ +public class PingResponseMqtt311OutMessage extends MqttOutMessage { + + private static final byte MESSAGE_TYPE = (byte) MqttMessageType.PING_RESPONSE.ordinal(); + + @Override + protected byte messageType() { + return MESSAGE_TYPE; + } +} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/PublishAck311OutPacket.java b/network/src/main/java/javasabr/mqtt/network/message/out/PublishAckMqtt311OutMessage.java similarity index 52% rename from network/src/main/java/javasabr/mqtt/network/packet/out/PublishAck311OutPacket.java rename to network/src/main/java/javasabr/mqtt/network/message/out/PublishAckMqtt311OutMessage.java index e40f465e..78bf688e 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/PublishAck311OutPacket.java +++ b/network/src/main/java/javasabr/mqtt/network/message/out/PublishAckMqtt311OutMessage.java @@ -1,22 +1,25 @@ -package javasabr.mqtt.network.packet.out; +package javasabr.mqtt.network.message.out; import java.nio.ByteBuffer; import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.MqttPacketType; +import javasabr.mqtt.network.message.MqttMessageType; +import lombok.AccessLevel; import lombok.RequiredArgsConstructor; +import lombok.experimental.FieldDefaults; /** * Publish acknowledgement. */ @RequiredArgsConstructor -public class PublishAck311OutPacket extends MqttWritablePacket { +@FieldDefaults(level = AccessLevel.PROTECTED, makeFinal = true) +public class PublishAckMqtt311OutMessage extends MqttOutMessage { - private static final byte PACKET_TYPE = (byte) MqttPacketType.PUBLISH_ACK.ordinal(); + private static final byte MESSAGE_TYPE = (byte) MqttMessageType.PUBLISH_ACK.ordinal(); /** * Packet Identifier from the PUBLISH packet that is being acknowledged. */ - private final int packetId; + int messageId; @Override public int expectedLength(MqttConnection connection) { @@ -24,13 +27,13 @@ public int expectedLength(MqttConnection connection) { } @Override - protected byte packetType() { - return PACKET_TYPE; + protected byte messageType() { + return MESSAGE_TYPE; } @Override protected void writeVariableHeader(MqttConnection connection, ByteBuffer buffer) { // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718045 - buffer.putShort((short) packetId); + buffer.putShort((short) messageId); } } diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/PublishAck5OutPacket.java b/network/src/main/java/javasabr/mqtt/network/message/out/PublishAckMqtt5OutMessage.java similarity index 85% rename from network/src/main/java/javasabr/mqtt/network/packet/out/PublishAck5OutPacket.java rename to network/src/main/java/javasabr/mqtt/network/message/out/PublishAckMqtt5OutMessage.java index 6b2ead54..e378d3d0 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/PublishAck5OutPacket.java +++ b/network/src/main/java/javasabr/mqtt/network/message/out/PublishAckMqtt5OutMessage.java @@ -1,4 +1,4 @@ -package javasabr.mqtt.network.packet.out; +package javasabr.mqtt.network.message.out; import java.nio.ByteBuffer; import java.util.EnumSet; @@ -8,11 +8,14 @@ import javasabr.mqtt.model.reason.code.PublishAckReasonCode; import javasabr.mqtt.network.MqttConnection; import javasabr.rlib.collections.array.Array; +import lombok.AccessLevel; +import lombok.experimental.FieldDefaults; /** * Publish acknowledgement. */ -public class PublishAck5OutPacket extends PublishAck311OutPacket { +@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) +public class PublishAckMqtt5OutMessage extends PublishAckMqtt311OutMessage { private static final Set AVAILABLE_PROPERTIES = EnumSet.of( /* @@ -35,16 +38,16 @@ public class PublishAck5OutPacket extends PublishAck311OutPacket { */ PacketProperty.USER_PROPERTY); - private final Array userProperties; - private final String reason; - private final PublishAckReasonCode reasonCode; + Array userProperties; + String reason; + PublishAckReasonCode reasonCode; - public PublishAck5OutPacket( - int packetId, + public PublishAckMqtt5OutMessage( + int messageId, PublishAckReasonCode reasonCode, Array userProperties, String reason) { - super(packetId); + super(messageId); this.reasonCode = reasonCode; this.userProperties = userProperties; this.reason = reason; diff --git a/network/src/main/java/javasabr/mqtt/network/message/out/PublishCompleteMqtt311OutMessage.java b/network/src/main/java/javasabr/mqtt/network/message/out/PublishCompleteMqtt311OutMessage.java new file mode 100644 index 00000000..dddd9205 --- /dev/null +++ b/network/src/main/java/javasabr/mqtt/network/message/out/PublishCompleteMqtt311OutMessage.java @@ -0,0 +1,36 @@ +package javasabr.mqtt.network.message.out; + +import java.nio.ByteBuffer; +import javasabr.mqtt.network.MqttConnection; +import javasabr.mqtt.network.message.MqttMessageType; +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; +import lombok.experimental.FieldDefaults; + +/** + * Publish complete (QoS 2 delivery part 3). + */ +@RequiredArgsConstructor +@FieldDefaults(level = AccessLevel.PROTECTED, makeFinal = true) +public class PublishCompleteMqtt311OutMessage extends MqttOutMessage { + + private static final byte MESSAGE_TYPE = (byte) MqttMessageType.PUBLISH_COMPLETED.ordinal(); + + int messageId; + + @Override + public int expectedLength(MqttConnection connection) { + return 2; + } + + @Override + protected byte messageType() { + return MESSAGE_TYPE; + } + + @Override + protected void writeVariableHeader(MqttConnection connection, ByteBuffer buffer) { + // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718083 + writeShort(buffer, messageId); + } +} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/PublishComplete5OutPacket.java b/network/src/main/java/javasabr/mqtt/network/message/out/PublishCompleteMqtt5OutMessage.java similarity index 81% rename from network/src/main/java/javasabr/mqtt/network/packet/out/PublishComplete5OutPacket.java rename to network/src/main/java/javasabr/mqtt/network/message/out/PublishCompleteMqtt5OutMessage.java index ed11e27c..91ca265f 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/PublishComplete5OutPacket.java +++ b/network/src/main/java/javasabr/mqtt/network/message/out/PublishCompleteMqtt5OutMessage.java @@ -1,4 +1,4 @@ -package javasabr.mqtt.network.packet.out; +package javasabr.mqtt.network.message.out; import java.nio.ByteBuffer; import java.util.EnumSet; @@ -9,11 +9,14 @@ import javasabr.mqtt.network.MqttConnection; import javasabr.rlib.collections.array.Array; import javasabr.rlib.common.util.StringUtils; +import lombok.AccessLevel; +import lombok.experimental.FieldDefaults; /** * Publish complete (QoS 2 delivery part 3). */ -public class PublishComplete5OutPacket extends PublishComplete311OutPacket { +@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) +public class PublishCompleteMqtt5OutMessage extends PublishCompleteMqtt311OutMessage { private static final Set AVAILABLE_PROPERTIES = EnumSet.of( /* @@ -36,20 +39,20 @@ public class PublishComplete5OutPacket extends PublishComplete311OutPacket { */ PacketProperty.USER_PROPERTY); - private final Array userProperties; - private final PublishCompletedReasonCode reasonCode; - private final String reason; + Array userProperties; + PublishCompletedReasonCode reasonCode; + String reason; - public PublishComplete5OutPacket(int packetId, PublishCompletedReasonCode reasonCode) { - this(packetId, reasonCode, Array.empty(StringPair.class), StringUtils.EMPTY); + public PublishCompleteMqtt5OutMessage(int messageId, PublishCompletedReasonCode reasonCode) { + this(messageId, reasonCode, Array.empty(StringPair.class), StringUtils.EMPTY); } - public PublishComplete5OutPacket( - int packetId, + public PublishCompleteMqtt5OutMessage( + int messageId, PublishCompletedReasonCode reasonCode, Array userProperties, String reason) { - super(packetId); + super(messageId); this.reasonCode = reasonCode; this.userProperties = userProperties; this.reason = reason; @@ -63,7 +66,6 @@ public int expectedLength(MqttConnection connection) { @Override protected void writeVariableHeader(MqttConnection connection, ByteBuffer buffer) { super.writeVariableHeader(connection, buffer); - // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901154 writeByte(buffer, reasonCode.getValue()); } @@ -76,7 +78,6 @@ protected boolean isPropertiesSupported(MqttConnection connection) { @Override protected void writeProperties(MqttConnection connection, ByteBuffer buffer) { super.writeProperties(connection, buffer); - // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901155 writeStringPairProperties(buffer, PacketProperty.USER_PROPERTY, userProperties); writeNotEmptyProperty(buffer, PacketProperty.REASON_STRING, reason); diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/Publish311OutPacket.java b/network/src/main/java/javasabr/mqtt/network/message/out/PublishMqtt311OutMessage.java similarity index 74% rename from network/src/main/java/javasabr/mqtt/network/packet/out/Publish311OutPacket.java rename to network/src/main/java/javasabr/mqtt/network/message/out/PublishMqtt311OutMessage.java index 6c8c5e3e..7f311372 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/Publish311OutPacket.java +++ b/network/src/main/java/javasabr/mqtt/network/message/out/PublishMqtt311OutMessage.java @@ -1,31 +1,34 @@ -package javasabr.mqtt.network.packet.out; +package javasabr.mqtt.network.message.out; import java.nio.ByteBuffer; import javasabr.mqtt.base.utils.DebugUtils; import javasabr.mqtt.model.QoS; import javasabr.mqtt.network.MqttConnection; +import lombok.AccessLevel; +import lombok.experimental.FieldDefaults; -public class Publish311OutPacket extends PublishOutPacket { +@FieldDefaults(level = AccessLevel.PROTECTED, makeFinal = true) +public class PublishMqtt311OutMessage extends PublishMqttOutMessage { static { DebugUtils.registerIncludedFields("qos", "topicName", "duplicate"); } - private final QoS qos; - private final byte[] payload; - private final String topicName; + QoS qos; + byte[] payload; + String topicName; - private final boolean retained; - private final boolean duplicate; + boolean retained; + boolean duplicate; - public Publish311OutPacket( - int packetId, + public PublishMqtt311OutMessage( + int messageId, QoS qos, boolean retained, boolean duplicate, String topicName, byte[] payload) { - super(packetId); + super(messageId); this.qos = qos; this.retained = retained; this.duplicate = duplicate; @@ -59,7 +62,7 @@ protected void writeVariableHeader(MqttConnection connection, ByteBuffer buffer) // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc384800412 writeString(buffer, topicName); if (qos.ordinal() > QoS.AT_MOST_ONCE.ordinal()) { - writeShort(buffer, packetId); + writeShort(buffer, messageId); } } diff --git a/network/src/main/java/javasabr/mqtt/network/message/out/PublishMqtt5OutMessage.java b/network/src/main/java/javasabr/mqtt/network/message/out/PublishMqtt5OutMessage.java new file mode 100644 index 00000000..cde19cee --- /dev/null +++ b/network/src/main/java/javasabr/mqtt/network/message/out/PublishMqtt5OutMessage.java @@ -0,0 +1,193 @@ +package javasabr.mqtt.network.message.out; + +import java.nio.ByteBuffer; +import java.util.EnumSet; +import java.util.Set; +import javasabr.mqtt.base.utils.DebugUtils; +import javasabr.mqtt.model.MqttProperties; +import javasabr.mqtt.model.PacketProperty; +import javasabr.mqtt.model.QoS; +import javasabr.mqtt.model.data.type.StringPair; +import javasabr.mqtt.network.MqttConnection; +import javasabr.rlib.collections.array.Array; +import lombok.AccessLevel; +import lombok.experimental.FieldDefaults; + +@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) +public class PublishMqtt5OutMessage extends PublishMqtt311OutMessage { + + static { + DebugUtils.registerIncludedFields("qos", "topicName", "duplicate"); + } + + private static final Set AVAILABLE_PROPERTIES = EnumSet.of( + /* + Followed by the value of the Payload Forma t Indicator, either of: + · 0 (0x00) Byte Indicates that the Payload is unspecified bytes, which is equivalent to not sending a + Payload Format Indicator. + · 1 (0x01) Byte Indicates that the Payload is UTF-8 Encoded Character Data. The UTF-8 data in the Payload + MUST be well-formed UTF-8 as defined by the Unicode specification [Unicode] and restated in RFC 3629 + [RFC3629]. + + A Server MUST send the Payload Format Indicator unaltered to all subscribers receiving the Application Message + [MQTT-3.3.2-4]. The receiver MAY validate that the Payload is of the format indicated, and if it is not send a + PUBACK, PUBREC, or DISCONNECT with Reason Code of 0x99 (Payload format invalid) as described in section 4.13. + Refer to section 5.4.9 for information about security issues in validating the payload format. + */ + PacketProperty.PAYLOAD_FORMAT_INDICATOR, + /* + Followed by the Four Byte Integer representing the Message Expiry Interval. + If present, the Four Byte value is the lifetime of the Application Message in seconds. If the Message Expiry + Interval has passed and the Server has not managed to start onward delivery to a matching subscriber, then it + MUST delete the copy of the message for that subscriber [MQTT-3.3.2-5]. + + If absent, the Application Message does not expire. + + The PUBLISH packet sent to a Client by the Server MUST contain a Message Expiry Interval set to the received + value minus the time that the Application Message has been waiting in the Server [MQTT-3.3.2-6]. Refer to + section 4.1 for details and limitations of stored state. + */ + PacketProperty.MESSAGE_EXPIRY_INTERVAL, + /* + Followed by the Two Byte integer representing the Topic Alias value. It is a Protocol Error to include the + Topic Alias value more than once. + + A Topic Alias is an integer value that is used to identify the Topic instead of using the Topic Name. This + reduces the size of the PUBLISH packet, and is useful when the Topic Names are long and the same Topic Names + are used repetitively within a Network Connection. + + The sender decides whether to use a Topic Alias and chooses the value. It sets a Topic Alias mapping by + including a non-zero length Topic Name and a Topic Alias in the PUBLISH packet. The receiver processes the + PUBLISH as normal but also sets the specified Topic Alias mapping to this Topic Name. + + If a Topic Alias mapping has been set at the receiver, a sender can send a PUBLISH packet that contains that + Topic Alias and a zero length Topic Name. The receiver then treats the incoming PUBLISH as if it had contained + the Topic Name of the Topic Alias. + + A sender can modify the Topic Alias mapping by sending another PUBLISH in the same Network Connection with the + same Topic Alias value and a different non-zero length Topic Name. + + Topic Alias mappings exist only within a Network Connection and last only for the lifetime of that Network + Connection. A receiver MUST NOT carry forward any Topic Alias mappings from one Network Connection to another + [MQTT-3.3.2-7]. + + A Topic Alias of 0 is not permitted. A sender MUST NOT send a PUBLISH packet containing a Topic Alias which + has the value 0 [MQTT-3.3.2-8]. + + A Client MUST NOT send a PUBLISH packet with a Topic Alias greater than the Topic Alias Maximum value returned + by the Server in the CONNACK packet [MQTT-3.3.2-9]. A Client MUST accept all Topic Alias values greater than 0 + and less than or equal to the Topic Alias Maximum value that it sent in the CONNECT packet [MQTT-3.3.2-10]. + + A Server MUST NOT send a PUBLISH packet with a Topic Alias greater than the Topic Alias Maximum value sent by + the Client in the CONNECT packet [MQTT-3.3.2-11]. A Server MUST accept all Topic Alias values greater than 0 + and less than or equal to the Topic Alias Maximum value that it returned in the CONNACK packet [MQTT-3.3.2-12] + + The Topic Alias mappings used by the Client and Server are independent from each other. Thus, when a Client + sends a PUBLISH containing a Topic Alias value of 1 to a Server and the Server sends a PUBLISH with a Topic + Alias value of 1 to that Client they will in general be referring to different Topics. + */ + PacketProperty.TOPIC_ALIAS, + /* + Followed by a UTF-8 Encoded String which is used as the Topic Name for a response message. The Response Topic + MUST be a UTF-8 Encoded String as defined in section 1.5.4 [MQTT-3.3.2-13]. The Response Topic MUST NOT + contain wildcard characters [MQTT-3.3.2-14]. It is a Protocol Error to include the Response Topic more than + once. The presence of a Response Topic identifies the Message as a Request. + + Refer to section 4.10 for more information about Request / Response. + + The Server MUST send the Response Topic unaltered to all subscribers receiving the Application Message + [MQTT-3.3.2-15]. + + Non-normative comment: + The receiver of an Application Message with a Response Topic sends a response by using the Response Topic as + the Topic Name of a PUBLISH. If the Request Message contains a Correlation Data, the receiver of the Request + Message should also include this Correlation Data as a property in the PUBLISH packet of the Response Message. + */ + PacketProperty.RESPONSE_TOPIC, + /* + Followed by Binary Data. The Correlation Data is used by the sender of the Request Message to identify which + request the Response Message is for when it is received. It is a Protocol Error to include Correlation Data + more than once. If the Correlation Data is not present, the Requester does not require any correlation data. + + The Server MUST send the Correlation Data unaltered to all subscribers receiving the Application Message + [MQTT-3.3.2-16]. The value of the Correlation Data only has meaning to the sender of the Request Message and + receiver of the Response Message. + + Non-normative comment + The receiver of an Application Message which contains both a Response Topic and a Correlation Data sends a + response by using the Response Topic as the Topic Name of a PUBLISH. The Client should also send the + Correlation Data unaltered as part of the PUBLISH of the responses. + + Non-normative comment + If the Correlation Data contains information which can cause application failures if modified by the Client + responding to the request, it should be encrypted and/or hashed to allow any alteration to be detected. + + Refer to section 4.10 for more information about Request / Response + */ + PacketProperty.CORRELATION_DATA, + /* + Followed by a UTF-8 String Pair. The User Property is allowed to appear multiple times to represent multiple + name, value pairs. The same name is allowed to appear more than once. + + The Server MUST send all User Properties unaltered in a PUBLISH packet when forwarding the Application Message + to a Client [MQTT-3.3.2-17]. The Server MUST maintain the order of User Properties when forwarding the + Application Message [MQTT-3.3.2-18]. + + Non-normative comment + This property is intended to provide a means of transferring application layer name-value tags whose meaning + and interpretation are known only by the application programs responsible for sending and receiving them. + */ + PacketProperty.USER_PROPERTY); + + String responseTopic; + byte[] correlationData; + Array userProperties; + + int topicAlias; + boolean stringPayload; + + public PublishMqtt5OutMessage( + int messageId, + QoS qos, + boolean retained, + boolean duplicate, + String topicName, + byte[] payload, + int topicAlias, + boolean stringPayload, + String responseTopic, + byte[] correlationData, + Array userProperties) { + super(messageId, qos, retained, duplicate, topicName, payload); + this.topicAlias = topicAlias; + this.stringPayload = stringPayload; + this.responseTopic = responseTopic; + this.correlationData = correlationData; + this.userProperties = userProperties; + } + + @Override + public int expectedLength(MqttConnection connection) { + return UNKNOWN_EXPECTED_BYTES; + } + + @Override + protected boolean isPropertiesSupported(MqttConnection connection) { + return true; + } + + @Override + protected void writeProperties(MqttConnection connection, ByteBuffer buffer) { + // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc511988586 + writeProperty(buffer, PacketProperty.PAYLOAD_FORMAT_INDICATOR, stringPayload); + writeProperty( + buffer, + PacketProperty.MESSAGE_EXPIRY_INTERVAL, + 0, + MqttProperties.MESSAGE_EXPIRY_INTERVAL_UNDEFINED); + writeProperty(buffer, PacketProperty.TOPIC_ALIAS, topicAlias, MqttProperties.TOPIC_ALIAS_DEFAULT); + writeNotEmptyProperty(buffer, PacketProperty.RESPONSE_TOPIC, responseTopic); + writeNotEmptyProperty(buffer, PacketProperty.CORRELATION_DATA, correlationData); + writeStringPairProperties(buffer, PacketProperty.USER_PROPERTY, userProperties); + } +} diff --git a/network/src/main/java/javasabr/mqtt/network/message/out/PublishMqttOutMessage.java b/network/src/main/java/javasabr/mqtt/network/message/out/PublishMqttOutMessage.java new file mode 100644 index 00000000..e72a876c --- /dev/null +++ b/network/src/main/java/javasabr/mqtt/network/message/out/PublishMqttOutMessage.java @@ -0,0 +1,25 @@ +package javasabr.mqtt.network.message.out; + +import javasabr.mqtt.network.message.HasMessageId; +import javasabr.mqtt.network.message.MqttMessageType; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.experimental.Accessors; +import lombok.experimental.FieldDefaults; + +@Accessors(fluent = true) +@RequiredArgsConstructor +@FieldDefaults(level = AccessLevel.PROTECTED, makeFinal = true) +public abstract class PublishMqttOutMessage extends MqttOutMessage implements HasMessageId { + + private static final byte MESSAGE_TYPE = (byte) MqttMessageType.PUBLISH.ordinal(); + + @Getter + int messageId; + + @Override + protected byte messageType() { + return MESSAGE_TYPE; + } +} diff --git a/network/src/main/java/javasabr/mqtt/network/message/out/PublishReceivedMqtt311OutMessage.java b/network/src/main/java/javasabr/mqtt/network/message/out/PublishReceivedMqtt311OutMessage.java new file mode 100644 index 00000000..b40d4ff2 --- /dev/null +++ b/network/src/main/java/javasabr/mqtt/network/message/out/PublishReceivedMqtt311OutMessage.java @@ -0,0 +1,36 @@ +package javasabr.mqtt.network.message.out; + +import java.nio.ByteBuffer; +import javasabr.mqtt.network.MqttConnection; +import javasabr.mqtt.network.message.MqttMessageType; +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; +import lombok.experimental.FieldDefaults; + +/** + * Publish received (QoS 2 delivery part 1). + */ +@RequiredArgsConstructor +@FieldDefaults(level = AccessLevel.PROTECTED, makeFinal = true) +public class PublishReceivedMqtt311OutMessage extends MqttOutMessage { + + private static final byte MESSAGE_TYPE = (byte) MqttMessageType.PUBLISH_RECEIVED.ordinal(); + + int messageId; + + @Override + public int expectedLength(MqttConnection connection) { + return 2; + } + + @Override + protected byte messageType() { + return MESSAGE_TYPE; + } + + @Override + protected void writeVariableHeader(MqttConnection connection, ByteBuffer buffer) { + // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718050 + writeShort(buffer, messageId); + } +} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/PublishReceived5OutPacket.java b/network/src/main/java/javasabr/mqtt/network/message/out/PublishReceivedMqtt5OutMessage.java similarity index 81% rename from network/src/main/java/javasabr/mqtt/network/packet/out/PublishReceived5OutPacket.java rename to network/src/main/java/javasabr/mqtt/network/message/out/PublishReceivedMqtt5OutMessage.java index 694068bc..8f7165fa 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/PublishReceived5OutPacket.java +++ b/network/src/main/java/javasabr/mqtt/network/message/out/PublishReceivedMqtt5OutMessage.java @@ -1,4 +1,4 @@ -package javasabr.mqtt.network.packet.out; +package javasabr.mqtt.network.message.out; import java.nio.ByteBuffer; import java.util.EnumSet; @@ -9,11 +9,14 @@ import javasabr.mqtt.network.MqttConnection; import javasabr.rlib.collections.array.Array; import javasabr.rlib.common.util.StringUtils; +import lombok.AccessLevel; +import lombok.experimental.FieldDefaults; /** * Publish received (QoS 2 delivery part 1). */ -public class PublishReceived5OutPacket extends PublishReceived311OutPacket { +@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) +public class PublishReceivedMqtt5OutMessage extends PublishReceivedMqtt311OutMessage { private static final Set AVAILABLE_PROPERTIES = EnumSet.of( /* @@ -36,20 +39,20 @@ public class PublishReceived5OutPacket extends PublishReceived311OutPacket { */ PacketProperty.USER_PROPERTY); - private final Array userProperties; - private final PublishReceivedReasonCode reasonCode; - private final String reason; + Array userProperties; + PublishReceivedReasonCode reasonCode; + String reason; - public PublishReceived5OutPacket(int packetId, PublishReceivedReasonCode reasonCode) { - this(packetId, reasonCode, Array.empty(StringPair.class), StringUtils.EMPTY); + public PublishReceivedMqtt5OutMessage(int messageId, PublishReceivedReasonCode reasonCode) { + this(messageId, reasonCode, Array.empty(StringPair.class), StringUtils.EMPTY); } - public PublishReceived5OutPacket( - int packetId, + public PublishReceivedMqtt5OutMessage( + int messageId, PublishReceivedReasonCode reasonCode, Array userProperties, String reason) { - super(packetId); + super(messageId); this.reasonCode = reasonCode; this.userProperties = userProperties; this.reason = reason; @@ -63,7 +66,6 @@ public int expectedLength(MqttConnection connection) { @Override protected void writeVariableHeader(MqttConnection connection, ByteBuffer buffer) { super.writeVariableHeader(connection, buffer); - // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901143 writeByte(buffer, reasonCode.value()); } @@ -76,7 +78,6 @@ protected boolean isPropertiesSupported(MqttConnection connection) { @Override protected void writeProperties(MqttConnection connection, ByteBuffer buffer) { super.writeProperties(connection, buffer); - // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901135 writeStringPairProperties(buffer, PacketProperty.USER_PROPERTY, userProperties); writeNotEmptyProperty(buffer, PacketProperty.REASON_STRING, reason); diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/PublishRelease311OutPacket.java b/network/src/main/java/javasabr/mqtt/network/message/out/PublishReleaseMqtt311OutMessage.java similarity index 52% rename from network/src/main/java/javasabr/mqtt/network/packet/out/PublishRelease311OutPacket.java rename to network/src/main/java/javasabr/mqtt/network/message/out/PublishReleaseMqtt311OutMessage.java index a1a6e9f7..a99e3048 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/PublishRelease311OutPacket.java +++ b/network/src/main/java/javasabr/mqtt/network/message/out/PublishReleaseMqtt311OutMessage.java @@ -1,23 +1,26 @@ -package javasabr.mqtt.network.packet.out; +package javasabr.mqtt.network.message.out; import java.nio.ByteBuffer; import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.MqttPacketType; +import javasabr.mqtt.network.message.MqttMessageType; +import lombok.AccessLevel; import lombok.RequiredArgsConstructor; +import lombok.experimental.FieldDefaults; /** * Publish release (QoS 2 delivery part 2). */ @RequiredArgsConstructor -public class PublishRelease311OutPacket extends MqttWritablePacket { +@FieldDefaults(level = AccessLevel.PROTECTED, makeFinal = true) +public class PublishReleaseMqtt311OutMessage extends MqttOutMessage { - private static final byte PACKET_TYPE = (byte) MqttPacketType.PUBLISH_RELEASED.ordinal(); + private static final byte MESSAGE_TYPE = (byte) MqttMessageType.PUBLISH_RELEASED.ordinal(); - private final int packetId; + int messageId; @Override - protected byte packetType() { - return PACKET_TYPE; + protected byte messageType() { + return MESSAGE_TYPE; } @Override @@ -33,6 +36,6 @@ public int expectedLength(MqttConnection connection) { @Override protected void writeVariableHeader(MqttConnection connection, ByteBuffer buffer) { // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718055 - writeShort(buffer, packetId); + writeShort(buffer, messageId); } } diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/PublishRelease5OutPacket.java b/network/src/main/java/javasabr/mqtt/network/message/out/PublishReleaseMqtt5OutMessage.java similarity index 86% rename from network/src/main/java/javasabr/mqtt/network/packet/out/PublishRelease5OutPacket.java rename to network/src/main/java/javasabr/mqtt/network/message/out/PublishReleaseMqtt5OutMessage.java index 88879cb3..db4f4244 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/PublishRelease5OutPacket.java +++ b/network/src/main/java/javasabr/mqtt/network/message/out/PublishReleaseMqtt5OutMessage.java @@ -1,4 +1,4 @@ -package javasabr.mqtt.network.packet.out; +package javasabr.mqtt.network.message.out; import java.nio.ByteBuffer; import java.util.EnumSet; @@ -8,11 +8,14 @@ import javasabr.mqtt.model.reason.code.PublishReleaseReasonCode; import javasabr.mqtt.network.MqttConnection; import javasabr.rlib.collections.array.Array; +import lombok.AccessLevel; +import lombok.experimental.FieldDefaults; /** * Publish release (QoS 2 delivery part 2). */ -public class PublishRelease5OutPacket extends PublishRelease311OutPacket { +@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) +public class PublishReleaseMqtt5OutMessage extends PublishReleaseMqtt311OutMessage { private static final Set AVAILABLE_PROPERTIES = EnumSet.of( /* @@ -35,16 +38,16 @@ public class PublishRelease5OutPacket extends PublishRelease311OutPacket { */ PacketProperty.USER_PROPERTY); - private final Array userProperties; - private final PublishReleaseReasonCode reasonCode; - private final String reason; + Array userProperties; + PublishReleaseReasonCode reasonCode; + String reason; - public PublishRelease5OutPacket( - int packetId, + public PublishReleaseMqtt5OutMessage( + int messageId, PublishReleaseReasonCode reasonCode, Array userProperties, String reason) { - super(packetId); + super(messageId); this.userProperties = userProperties; this.reasonCode = reasonCode; this.reason = reason; @@ -58,7 +61,6 @@ public int expectedLength(MqttConnection connection) { @Override protected void writeVariableHeader(MqttConnection connection, ByteBuffer buffer) { super.writeVariableHeader(connection, buffer); - // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901144 writeByte(buffer, reasonCode.getValue()); } @@ -71,7 +73,6 @@ protected boolean isPropertiesSupported(MqttConnection connection) { @Override protected void writeProperties(MqttConnection connection, ByteBuffer buffer) { super.writeProperties(connection, buffer); - // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901145 writeStringPairProperties(buffer, PacketProperty.USER_PROPERTY, userProperties); writeNotEmptyProperty(buffer, PacketProperty.REASON_STRING, reason); diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/SubscribeAck311OutPacket.java b/network/src/main/java/javasabr/mqtt/network/message/out/SubscribeAckMqtt311OutMessage.java similarity index 75% rename from network/src/main/java/javasabr/mqtt/network/packet/out/SubscribeAck311OutPacket.java rename to network/src/main/java/javasabr/mqtt/network/message/out/SubscribeAckMqtt311OutMessage.java index f1cbc40b..312f5c8d 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/SubscribeAck311OutPacket.java +++ b/network/src/main/java/javasabr/mqtt/network/message/out/SubscribeAckMqtt311OutMessage.java @@ -1,10 +1,10 @@ -package javasabr.mqtt.network.packet.out; +package javasabr.mqtt.network.message.out; import java.nio.ByteBuffer; import javasabr.mqtt.base.utils.DebugUtils; import javasabr.mqtt.model.reason.code.SubscribeAckReasonCode; import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.MqttPacketType; +import javasabr.mqtt.network.message.MqttMessageType; import javasabr.rlib.collections.array.Array; import lombok.AccessLevel; import lombok.RequiredArgsConstructor; @@ -15,12 +15,12 @@ */ @RequiredArgsConstructor @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) -public class SubscribeAck311OutPacket extends MqttWritablePacket { +public class SubscribeAckMqtt311OutMessage extends MqttOutMessage { - private static final byte PACKET_TYPE = (byte) MqttPacketType.SUBSCRIBE_ACK.ordinal(); + private static final byte MESSAGE_TYPE = (byte) MqttMessageType.SUBSCRIBE_ACK.ordinal(); static { - DebugUtils.registerIncludedFields("reasonCodes", "packetId"); + DebugUtils.registerIncludedFields("reasonCodes", "messageId"); } /** @@ -31,7 +31,7 @@ public class SubscribeAck311OutPacket extends MqttWritablePacket { /** * The Packet Identifier from the SUBSCRIBE. */ - int packetId; + int messageId; @Override public int expectedLength(MqttConnection connection) { @@ -39,14 +39,14 @@ public int expectedLength(MqttConnection connection) { } @Override - protected byte packetType() { - return PACKET_TYPE; + protected byte messageType() { + return MESSAGE_TYPE; } @Override protected void writeVariableHeader(MqttConnection connection, ByteBuffer buffer) { // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718070 - writeShort(buffer, packetId); + writeShort(buffer, messageId); } @Override diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/SubscribeAck5OutPacket.java b/network/src/main/java/javasabr/mqtt/network/message/out/SubscribeAckMqtt5OutMessage.java similarity index 82% rename from network/src/main/java/javasabr/mqtt/network/packet/out/SubscribeAck5OutPacket.java rename to network/src/main/java/javasabr/mqtt/network/message/out/SubscribeAckMqtt5OutMessage.java index bc45b019..cdf81ef8 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/SubscribeAck5OutPacket.java +++ b/network/src/main/java/javasabr/mqtt/network/message/out/SubscribeAckMqtt5OutMessage.java @@ -1,4 +1,4 @@ -package javasabr.mqtt.network.packet.out; +package javasabr.mqtt.network.message.out; import java.nio.ByteBuffer; import java.util.EnumSet; @@ -9,14 +9,17 @@ import javasabr.mqtt.model.reason.code.SubscribeAckReasonCode; import javasabr.mqtt.network.MqttConnection; import javasabr.rlib.collections.array.Array; +import lombok.AccessLevel; +import lombok.experimental.FieldDefaults; /** * Subscribe acknowledgement. */ -public class SubscribeAck5OutPacket extends SubscribeAck311OutPacket { +@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) +public class SubscribeAckMqtt5OutMessage extends SubscribeAckMqtt311OutMessage { static { - DebugUtils.registerIncludedFields("reasonCodes", "packetId"); + DebugUtils.registerIncludedFields("reasonCodes", "messageId"); } private static final Set AVAILABLE_PROPERTIES = EnumSet.of( @@ -39,15 +42,15 @@ public class SubscribeAck5OutPacket extends SubscribeAck311OutPacket { */ PacketProperty.USER_PROPERTY); - private final Array userProperties; - private final String reason; + Array userProperties; + String reason; - public SubscribeAck5OutPacket( - int packetId, + public SubscribeAckMqtt5OutMessage( + int messageId, Array reasonCodes, Array userProperties, String reason) { - super(reasonCodes, packetId); + super(reasonCodes, messageId); this.userProperties = userProperties; this.reason = reason; } diff --git a/network/src/main/java/javasabr/mqtt/network/message/out/SubscribeMqtt311OutMessage.java b/network/src/main/java/javasabr/mqtt/network/message/out/SubscribeMqtt311OutMessage.java new file mode 100644 index 00000000..49404549 --- /dev/null +++ b/network/src/main/java/javasabr/mqtt/network/message/out/SubscribeMqtt311OutMessage.java @@ -0,0 +1,49 @@ +package javasabr.mqtt.network.message.out; + +import java.nio.ByteBuffer; +import javasabr.mqtt.model.subscriber.SubscribeTopicFilter; +import javasabr.mqtt.model.topic.TopicFilter; +import javasabr.mqtt.network.MqttConnection; +import javasabr.mqtt.network.message.MqttMessageType; +import javasabr.rlib.collections.array.Array; +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; +import lombok.experimental.FieldDefaults; + +/** + * Subscribe request. + */ +@RequiredArgsConstructor +@FieldDefaults(level = AccessLevel.PROTECTED, makeFinal = true) +public class SubscribeMqtt311OutMessage extends MqttOutMessage { + + private static final byte MESSAGE_TYPE = (byte) MqttMessageType.SUBSCRIBE.ordinal(); + + Array topicFilters; + int messageId; + + @Override + protected byte messageType() { + return MESSAGE_TYPE; + } + + @Override + protected void writeVariableHeader(MqttConnection connection, ByteBuffer buffer) { + // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718065 + writeShort(buffer, messageId); + } + + @Override + protected void writePayload(MqttConnection connection, ByteBuffer buffer) { + // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718066 + for (SubscribeTopicFilter subscribedTopic : topicFilters) { + TopicFilter topicFilter = subscribedTopic.getTopicFilter(); + writeString(buffer, topicFilter.toString()); + writeByte(buffer, buildSubscriptionOptions(subscribedTopic)); + } + } + + protected int buildSubscriptionOptions(SubscribeTopicFilter topicFilter) { + return topicFilter.getQos().ordinal(); + } +} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/Subscribe5OutPacket.java b/network/src/main/java/javasabr/mqtt/network/message/out/SubscribeMqtt5OutMessage.java similarity index 73% rename from network/src/main/java/javasabr/mqtt/network/packet/out/Subscribe5OutPacket.java rename to network/src/main/java/javasabr/mqtt/network/message/out/SubscribeMqtt5OutMessage.java index 49a75f65..7e5456e3 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/Subscribe5OutPacket.java +++ b/network/src/main/java/javasabr/mqtt/network/message/out/SubscribeMqtt5OutMessage.java @@ -1,19 +1,24 @@ -package javasabr.mqtt.network.packet.out; +package javasabr.mqtt.network.message.out; import java.nio.ByteBuffer; import java.util.EnumSet; import java.util.Set; import javasabr.mqtt.model.MqttProperties; import javasabr.mqtt.model.PacketProperty; +import javasabr.mqtt.model.QoS; +import javasabr.mqtt.model.SubscribeRetainHandling; import javasabr.mqtt.model.data.type.StringPair; import javasabr.mqtt.model.subscriber.SubscribeTopicFilter; import javasabr.mqtt.network.MqttConnection; import javasabr.rlib.collections.array.Array; +import lombok.AccessLevel; +import lombok.experimental.FieldDefaults; /** * Subscribe request. */ -public class Subscribe5OutPacket extends Subscribe311OutPacket { +@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) +public class SubscribeMqtt5OutMessage extends SubscribeMqtt311OutMessage { private static final Set AVAILABLE_PROPERTIES = EnumSet.of( /* @@ -34,30 +39,30 @@ public class Subscribe5OutPacket extends Subscribe311OutPacket { PacketProperty.USER_PROPERTY); // properties - private final Array userProperties; - private final int subscriptionId; + Array userProperties; + int subscriptionId; - public Subscribe5OutPacket(Array topicFilters, int packetId) { - this(topicFilters, packetId, Array.empty(StringPair.class), MqttProperties.SUBSCRIPTION_ID_UNDEFINED); + public SubscribeMqtt5OutMessage(Array topicFilters, int messageId) { + this(topicFilters, messageId, Array.empty(StringPair.class), MqttProperties.SUBSCRIPTION_ID_UNDEFINED); } - public Subscribe5OutPacket( + public SubscribeMqtt5OutMessage( Array topicFilters, - int packetId, + int messageId, Array userProperties, int subscriptionId) { - super(topicFilters, packetId); + super(topicFilters, messageId); this.userProperties = userProperties; this.subscriptionId = subscriptionId; } protected int buildSubscriptionOptions(SubscribeTopicFilter topicFilter) { - var subscriptionOptions = 0; + SubscribeRetainHandling retainHandling = topicFilter.getRetainHandling(); + QoS qos = topicFilter.getQos(); - subscriptionOptions |= topicFilter - .getRetainHandling() - .ordinal() << 4; + var subscriptionOptions = 0; + subscriptionOptions |= retainHandling.ordinal() << 4; if (topicFilter.isRetainAsPublished()) { subscriptionOptions |= 0b0000_1000; @@ -67,9 +72,7 @@ protected int buildSubscriptionOptions(SubscribeTopicFilter topicFilter) { subscriptionOptions |= 0b0000_0100; } - subscriptionOptions |= topicFilter - .getQos() - .ordinal(); + subscriptionOptions |= qos.ordinal(); return subscriptionOptions; } diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/UnsubscribeAck311OutPacket.java b/network/src/main/java/javasabr/mqtt/network/message/out/UnsubscribeAckMqtt311OutMessage.java similarity index 51% rename from network/src/main/java/javasabr/mqtt/network/packet/out/UnsubscribeAck311OutPacket.java rename to network/src/main/java/javasabr/mqtt/network/message/out/UnsubscribeAckMqtt311OutMessage.java index 48bf069b..01e95475 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/UnsubscribeAck311OutPacket.java +++ b/network/src/main/java/javasabr/mqtt/network/message/out/UnsubscribeAckMqtt311OutMessage.java @@ -1,19 +1,22 @@ -package javasabr.mqtt.network.packet.out; +package javasabr.mqtt.network.message.out; import java.nio.ByteBuffer; import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.MqttPacketType; +import javasabr.mqtt.network.message.MqttMessageType; +import lombok.AccessLevel; import lombok.RequiredArgsConstructor; +import lombok.experimental.FieldDefaults; /** * Unsubscribe acknowledgement. */ @RequiredArgsConstructor -public class UnsubscribeAck311OutPacket extends MqttWritablePacket { +@FieldDefaults(level = AccessLevel.PROTECTED, makeFinal = true) +public class UnsubscribeAckMqtt311OutMessage extends MqttOutMessage { - private static final byte PACKET_TYPE = (byte) MqttPacketType.UNSUBSCRIBE_ACK.ordinal(); + private static final byte PACKET_TYPE = (byte) MqttMessageType.UNSUBSCRIBE_ACK.ordinal(); - private final int packetId; + int messageId; @Override public int expectedLength(MqttConnection connection) { @@ -21,13 +24,13 @@ public int expectedLength(MqttConnection connection) { } @Override - protected byte packetType() { + protected byte messageType() { return PACKET_TYPE; } @Override protected void writeVariableHeader(MqttConnection connection, ByteBuffer buffer) { // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718074 - writeShort(buffer, packetId); + writeShort(buffer, messageId); } } diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/UnsubscribeAck5OutPacket.java b/network/src/main/java/javasabr/mqtt/network/message/out/UnsubscribeAckMqtt5OutMessage.java similarity index 92% rename from network/src/main/java/javasabr/mqtt/network/packet/out/UnsubscribeAck5OutPacket.java rename to network/src/main/java/javasabr/mqtt/network/message/out/UnsubscribeAckMqtt5OutMessage.java index e236e7c3..8724c636 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/UnsubscribeAck5OutPacket.java +++ b/network/src/main/java/javasabr/mqtt/network/message/out/UnsubscribeAckMqtt5OutMessage.java @@ -1,4 +1,4 @@ -package javasabr.mqtt.network.packet.out; +package javasabr.mqtt.network.message.out; import java.nio.ByteBuffer; import java.util.EnumSet; @@ -15,7 +15,7 @@ * Unsubscribe acknowledgement. */ @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) -public class UnsubscribeAck5OutPacket extends UnsubscribeAck311OutPacket { +public class UnsubscribeAckMqtt5OutMessage extends UnsubscribeAckMqtt311OutMessage { private static final Set AVAILABLE_PROPERTIES = EnumSet.of( /* @@ -42,12 +42,12 @@ public class UnsubscribeAck5OutPacket extends UnsubscribeAck311OutPacket { Array userProperties; String reason; - public UnsubscribeAck5OutPacket( - int packetId, + public UnsubscribeAckMqtt5OutMessage( + int messageId, Array reasonCodes, Array userProperties, String reason) { - super(packetId); + super(messageId); this.reasonCodes = reasonCodes; this.userProperties = userProperties; this.reason = reason; @@ -60,7 +60,6 @@ protected boolean isPropertiesSupported(MqttConnection connection) { @Override protected void writeProperties(MqttConnection connection, ByteBuffer buffer) { - // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901182 writeStringPairProperties(buffer, PacketProperty.USER_PROPERTY, userProperties); writeNotEmptyProperty(buffer, PacketProperty.REASON_STRING, reason); diff --git a/network/src/main/java/javasabr/mqtt/network/packet/in/package-info.java b/network/src/main/java/javasabr/mqtt/network/message/out/package-info.java similarity index 56% rename from network/src/main/java/javasabr/mqtt/network/packet/in/package-info.java rename to network/src/main/java/javasabr/mqtt/network/message/out/package-info.java index 54bf77e8..457466c9 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/in/package-info.java +++ b/network/src/main/java/javasabr/mqtt/network/message/out/package-info.java @@ -1,4 +1,4 @@ @NullMarked -package javasabr.mqtt.network.packet.in; +package javasabr.mqtt.network.message.out; import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/network/src/main/java/javasabr/mqtt/network/packet/package-info.java b/network/src/main/java/javasabr/mqtt/network/message/package-info.java similarity index 58% rename from network/src/main/java/javasabr/mqtt/network/packet/package-info.java rename to network/src/main/java/javasabr/mqtt/network/message/package-info.java index 78381ac0..c96194e9 100644 --- a/network/src/main/java/javasabr/mqtt/network/packet/package-info.java +++ b/network/src/main/java/javasabr/mqtt/network/message/package-info.java @@ -1,4 +1,4 @@ @NullMarked -package javasabr.mqtt.network.packet; +package javasabr.mqtt.network.message; import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/network/src/main/java/javasabr/mqtt/network/packet/HasPacketId.java b/network/src/main/java/javasabr/mqtt/network/packet/HasPacketId.java deleted file mode 100644 index 6d3d3c6e..00000000 --- a/network/src/main/java/javasabr/mqtt/network/packet/HasPacketId.java +++ /dev/null @@ -1,9 +0,0 @@ -package javasabr.mqtt.network.packet; - -import javasabr.mqtt.network.MqttConnection; -import javasabr.rlib.network.packet.NetworkPacket; - -public interface HasPacketId extends NetworkPacket { - - int packetId(); -} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/MqttPacketReader.java b/network/src/main/java/javasabr/mqtt/network/packet/MqttPacketReader.java deleted file mode 100644 index d73b665f..00000000 --- a/network/src/main/java/javasabr/mqtt/network/packet/MqttPacketReader.java +++ /dev/null @@ -1,96 +0,0 @@ -package javasabr.mqtt.network.packet; - -import java.nio.ByteBuffer; -import java.util.NoSuchElementException; -import java.util.function.Consumer; -import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.in.AuthenticationInPacket; -import javasabr.mqtt.network.packet.in.ConnectAckInPacket; -import javasabr.mqtt.network.packet.in.ConnectInPacket; -import javasabr.mqtt.network.packet.in.DisconnectInPacket; -import javasabr.mqtt.network.packet.in.MqttReadablePacket; -import javasabr.mqtt.network.packet.in.PingRequestInPacket; -import javasabr.mqtt.network.packet.in.PingResponseInPacket; -import javasabr.mqtt.network.packet.in.PublishAckInPacket; -import javasabr.mqtt.network.packet.in.PublishCompleteInPacket; -import javasabr.mqtt.network.packet.in.PublishInPacket; -import javasabr.mqtt.network.packet.in.PublishReceivedInPacket; -import javasabr.mqtt.network.packet.in.PublishReleaseInPacket; -import javasabr.mqtt.network.packet.in.SubscribeAckInPacket; -import javasabr.mqtt.network.packet.in.SubscribeInPacket; -import javasabr.mqtt.network.packet.in.UnsubscribeAckInPacket; -import javasabr.mqtt.network.packet.in.UnsubscribeInPacket; -import javasabr.mqtt.network.utils.MqttDataUtils; -import javasabr.rlib.common.util.ArrayUtils; -import javasabr.rlib.common.util.NumberUtils; -import javasabr.rlib.functions.ByteFunction; -import javasabr.rlib.network.packet.impl.AbstractNetworkPacketReader; -import org.jspecify.annotations.Nullable; - -public class MqttPacketReader extends AbstractNetworkPacketReader { - - private static final int PACKET_LENGTH_START_BYTE = 2; - - private static final ByteFunction[] PACKET_FACTORIES = ArrayUtils.array( - id -> {throw new NoSuchElementException();}, - ConnectInPacket::new, - ConnectAckInPacket::new, - PublishInPacket::new, - PublishAckInPacket::new, - PublishReceivedInPacket::new, - PublishReleaseInPacket::new, - PublishCompleteInPacket::new, - SubscribeInPacket::new, - SubscribeAckInPacket::new, - UnsubscribeInPacket::new, - UnsubscribeAckInPacket::new, - PingRequestInPacket::new, - PingResponseInPacket::new, - DisconnectInPacket::new, - AuthenticationInPacket::new); - - public MqttPacketReader( - MqttConnection connection, - Runnable updateActivityFunction, - Consumer readPacketHandler, - int maxPacketsByRead) { - super(connection, updateActivityFunction, readPacketHandler, maxPacketsByRead); - } - - @Override - protected boolean canStartReadPacket(ByteBuffer buffer) { - return buffer.remaining() >= PACKET_LENGTH_START_BYTE; - } - - @Override - protected int readFullPacketLength(ByteBuffer buffer) { - // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901021 - int prevPos = buffer.position(); - - // skip first byte of packet type - buffer.get(); - int dataSize = MqttDataUtils.readMbi(buffer); - if (dataSize == -1) { - return -1; - } - - int readBytes = buffer.position() - prevPos; - return dataSize + readBytes; - } - - @Nullable - @Override - protected MqttReadablePacket createPacketFor( - ByteBuffer buffer, - int startPacketPosition, - int packetLength, - int dataLength) { - - // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901021 - var startByte = Byte.toUnsignedInt(buffer.get(startPacketPosition)); - var type = NumberUtils.getHighByteBits(startByte); - var info = NumberUtils.getLowByteBits(startByte); - - return PACKET_FACTORIES[type].apply(info); - } -} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/in/AuthenticationInPacket.java b/network/src/main/java/javasabr/mqtt/network/packet/in/AuthenticationInPacket.java deleted file mode 100644 index 38886277..00000000 --- a/network/src/main/java/javasabr/mqtt/network/packet/in/AuthenticationInPacket.java +++ /dev/null @@ -1,109 +0,0 @@ -package javasabr.mqtt.network.packet.in; - -import java.nio.ByteBuffer; -import java.util.EnumSet; -import java.util.Set; -import javasabr.mqtt.model.PacketProperty; -import javasabr.mqtt.model.reason.code.AuthenticateReasonCode; -import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.MqttPacketType; -import javasabr.rlib.common.util.ArrayUtils; -import javasabr.rlib.common.util.StringUtils; -import lombok.Getter; - -/** - * Authentication exchange. - */ -@Getter -public class AuthenticationInPacket extends MqttReadablePacket { - - private static final byte PACKET_TYPE = (byte) MqttPacketType.AUTHENTICATE.ordinal(); - - private static final Set AVAILABLE_PROPERTIES = EnumSet.of( - /* - Followed by a UTF-8 Encoded String containing the name of the authentication method. It is a Protocol - Error to omit the Authentication Method or to include it more than once. Refer to section 4.12 for more - information about extended authentication. - */ - PacketProperty.AUTHENTICATION_METHOD, - /* - Followed by Binary Data containing authentication data. It is a Protocol Error to include Authentication - Data more than once. The contents of this data are defined by the authentication method. Refer to - section 4.12 for more information about extended authentication. - */ - PacketProperty.AUTHENTICATION_DATA, - /* - Followed by the UTF-8 Encoded String representing the reason for the disconnect. This Reason String is - human readable, designed for diagnostics and SHOULD NOT be parsed by the receiver. - - The sender MUST NOT send this property if it would increase the size of the AUTH packet beyond the - Maximum Packet Size specified by the receiver [MQTT-3.15.2-2]. It is a Protocol Error to include the - Reason String more than once. - */ - PacketProperty.REASON_STRING, - /* - Followed by UTF-8 String Pair. This property may be used to provide additional diagnostic or other - information. The sender MUST NOT send this property if it would increase the size of the AUTH packet - beyond the Maximum Packet Size specified by the receiver [MQTT-3.15.2-3]. The User Property is - allowed to appear multiple times to represent multiple name, value pairs. The same name is allowed to - appear more than once. - */ - PacketProperty.USER_PROPERTY); - - private AuthenticateReasonCode reasonCode; - - // properties - private String reason; - private String authenticationMethod; - - private byte[] authenticationData; - - public AuthenticationInPacket(byte info) { - super(info); - this.reasonCode = AuthenticateReasonCode.SUCCESS; - this.reason = StringUtils.EMPTY; - this.authenticationMethod = StringUtils.EMPTY; - this.authenticationData = ArrayUtils.EMPTY_BYTE_ARRAY; - } - - @Override - public byte packetType() { - return PACKET_TYPE; - } - - @Override - protected void readVariableHeader(MqttConnection connection, ByteBuffer buffer) { - // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901219 - reasonCode = AuthenticateReasonCode.of(readByteUnsigned(buffer)); - } - - @Override - protected Set getAvailableProperties() { - return AVAILABLE_PROPERTIES; - } - - @Override - protected void applyProperty(PacketProperty property, byte[] value) { - switch (property) { - case AUTHENTICATION_DATA: - authenticationData = value; - break; - default: - unexpectedProperty(property); - } - } - - @Override - protected void applyProperty(PacketProperty property, String value) { - switch (property) { - case REASON_STRING: - reason = value; - break; - case AUTHENTICATION_METHOD: - authenticationMethod = value; - break; - default: - unexpectedProperty(property); - } - } -} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/in/DisconnectInPacket.java b/network/src/main/java/javasabr/mqtt/network/packet/in/DisconnectInPacket.java deleted file mode 100644 index b38308e0..00000000 --- a/network/src/main/java/javasabr/mqtt/network/packet/in/DisconnectInPacket.java +++ /dev/null @@ -1,131 +0,0 @@ -package javasabr.mqtt.network.packet.in; - -import java.nio.ByteBuffer; -import java.util.EnumSet; -import java.util.Set; -import javasabr.mqtt.base.utils.DebugUtils; -import javasabr.mqtt.model.MqttProperties; -import javasabr.mqtt.model.MqttVersion; -import javasabr.mqtt.model.PacketProperty; -import javasabr.mqtt.model.reason.code.DisconnectReasonCode; -import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.MqttPacketType; -import javasabr.rlib.common.util.StringUtils; -import lombok.Getter; - -/** - * Disconnect notification. - */ -@Getter -public class DisconnectInPacket extends MqttReadablePacket { - - public static final byte PACKET_TYPE = (byte) MqttPacketType.DISCONNECT.ordinal(); - - static { - DebugUtils.registerIncludedFields("reasonCode"); - } - - private static final Set AVAILABLE_PROPERTIES = EnumSet.of( - /* - If the Session Expiry Interval is absent, the Session Expiry Interval in the CONNECT packet is used. - - The Session Expiry Interval MUST NOT be sent on a DISCONNECT by the Server [MQTT-3.14.2-2]. - - If the Session Expiry Interval in the CONNECT packet was zero, then it is a Protocol Error to set a non - zero Session Expiry Interval in the DISCONNECT packet sent by the Client. If such a non-zero Session - Expiry Interval is received by the Server, it does not treat it as a valid DISCONNECT packet. The Server - uses DISCONNECT with Reason Code 0x82 (Protocol Error) as described in - */ - PacketProperty.SESSION_EXPIRY_INTERVAL, - /* - The sender MUST NOT send this Property if it would increase the size of the DISCONNECT packet - beyond the Maximum Packet Size specified by the receiver [MQTT-3.14.2-3]. It is a Protocol Error to - include the Reason String more than once. - */ - PacketProperty.REASON_STRING, - /* - Followed by UTF-8 String Pair. This property may be used to provide additional diagnostic or other - information. The sender MUST NOT send this property if it would increase the size of the DISCONNECT - packet beyond the Maximum Packet Size specified by the receiver [MQTT-3.14.2-4]. The User Property is - allowed to appear multiple times to represent multiple name, value pairs. The same name is allowed to - appear more than once. - */ - PacketProperty.USER_PROPERTY, - /* - The Server sends DISCONNECT including a Server Reference and Reason Code {0x9C (Use another - 2601 server)} or 0x9D (Server moved) as described in section 4.13. - */ - PacketProperty.SERVER_REFERENCE); - - private DisconnectReasonCode reasonCode; - - // properties - private String reason; - private String serverReference; - - private long sessionExpiryInterval; - - public DisconnectInPacket(byte info) { - super(info); - this.reasonCode = DisconnectReasonCode.NORMAL_DISCONNECTION; - this.reason = StringUtils.EMPTY; - this.serverReference = StringUtils.EMPTY; - this.sessionExpiryInterval = MqttProperties.SESSION_EXPIRY_INTERVAL_DEFAULT; - } - - @Override - public byte packetType() { - return PACKET_TYPE; - } - - @Override - protected void readImpl(MqttConnection connection, ByteBuffer buffer) { - this.sessionExpiryInterval = connection - .clientConnectionConfig() - .sessionExpiryInterval(); - super.readImpl(connection, buffer); - } - - @Override - protected void readVariableHeader(MqttConnection connection, ByteBuffer buffer) { - // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901207 - if (connection.isSupported(MqttVersion.MQTT_5) && buffer.hasRemaining()) { - reasonCode = DisconnectReasonCode.of(readByteUnsigned(buffer)); - } - } - - @Override - protected boolean isPropertiesSupported(MqttConnection connection, ByteBuffer buffer) { - return connection.isSupported(MqttVersion.MQTT_5) && buffer.hasRemaining(); - } - - @Override - protected Set getAvailableProperties() { - return AVAILABLE_PROPERTIES; - } - - @Override - protected void applyProperty(PacketProperty property, long value) { - switch (property) { - case SESSION_EXPIRY_INTERVAL: - sessionExpiryInterval = value; - break; - default: - unexpectedProperty(property); - } - } - - @Override - protected void applyProperty(PacketProperty property, String value) { - switch (property) { - case REASON_STRING: - reason = value; - break; - case SERVER_REFERENCE: - serverReference = value; - break; - default: - unexpectedProperty(property); - } - } -} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/in/PingRequestInPacket.java b/network/src/main/java/javasabr/mqtt/network/packet/in/PingRequestInPacket.java deleted file mode 100644 index c5aeaece..00000000 --- a/network/src/main/java/javasabr/mqtt/network/packet/in/PingRequestInPacket.java +++ /dev/null @@ -1,20 +0,0 @@ -package javasabr.mqtt.network.packet.in; - -import javasabr.mqtt.network.packet.MqttPacketType; - -/** - * PING request. - */ -public class PingRequestInPacket extends MqttReadablePacket { - - public static final byte PACKET_TYPE = (byte) MqttPacketType.PING_REQUEST.ordinal(); - - public PingRequestInPacket(byte info) { - super(info); - } - - @Override - public byte packetType() { - return PACKET_TYPE; - } -} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/in/PingResponseInPacket.java b/network/src/main/java/javasabr/mqtt/network/packet/in/PingResponseInPacket.java deleted file mode 100644 index 516d50ac..00000000 --- a/network/src/main/java/javasabr/mqtt/network/packet/in/PingResponseInPacket.java +++ /dev/null @@ -1,20 +0,0 @@ -package javasabr.mqtt.network.packet.in; - -import javasabr.mqtt.network.packet.MqttPacketType; - -/** - * PING response. - */ -public class PingResponseInPacket extends MqttReadablePacket { - - public static final byte PACKET_TYPE = (byte) MqttPacketType.PING_RESPONSE.ordinal(); - - public PingResponseInPacket(byte info) { - super(info); - } - - @Override - public byte packetType() { - return PACKET_TYPE; - } -} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/in/PublishAckInPacket.java b/network/src/main/java/javasabr/mqtt/network/packet/in/PublishAckInPacket.java deleted file mode 100644 index 417f08e9..00000000 --- a/network/src/main/java/javasabr/mqtt/network/packet/in/PublishAckInPacket.java +++ /dev/null @@ -1,99 +0,0 @@ -package javasabr.mqtt.network.packet.in; - -import java.nio.ByteBuffer; -import java.util.EnumSet; -import java.util.Set; -import javasabr.mqtt.base.utils.DebugUtils; -import javasabr.mqtt.model.MqttVersion; -import javasabr.mqtt.model.PacketProperty; -import javasabr.mqtt.model.reason.code.PublishAckReasonCode; -import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.HasPacketId; -import javasabr.mqtt.network.packet.MqttPacketType; -import lombok.Getter; -import lombok.experimental.Accessors; - -/** - * Publish acknowledgment (QoS 1). - */ -@Getter -@Accessors(fluent = true, chain = false) -public class PublishAckInPacket extends MqttReadablePacket implements HasPacketId { - - private static final int PACKET_TYPE = MqttPacketType.PUBLISH_ACK.ordinal(); - - static { - DebugUtils.registerIncludedFields("reasonCode", "packetId"); - } - - private static final Set AVAILABLE_PROPERTIES = EnumSet.of( - /* - Followed by the UTF-8 Encoded String representing the reason associated with this response. This - Reason String is a human readable string designed for diagnostics and is not intended to be parsed by - the receiver. - - The sender uses this value to give additional information to the receiver. The sender MUST NOT send - this property if it would increase the size of the PUBACK packet beyond the Maximum Packet Size - specified by the receiver [MQTT-3.4.2-2]. It is a Protocol Error to include the Reason String more than - once. - */ - PacketProperty.REASON_STRING, - /* - Followed by UTF-8 String Pair. This property can be used to provide additional diagnostic or other - information. The sender MUST NOT send this property if it would increase the size of the PUBACK - packet beyond the Maximum Packet Size specified by the receiver [MQTT-3.4.2-3]. The User Property is - allowed to appear multiple times to represent multiple name, value pairs. The same name is allowed to - appear more than once. - */ - PacketProperty.USER_PROPERTY); - - private PublishAckReasonCode reasonCode; - private int packetId; - - // properties - private String reason; - - public PublishAckInPacket(byte info) { - super(info); - this.reasonCode = PublishAckReasonCode.SUCCESS; - this.reason = ""; - } - - @Override - public byte packetType() { - return (byte) PACKET_TYPE; - } - - @Override - protected void readVariableHeader(MqttConnection connection, ByteBuffer buffer) { - - // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718045 - packetId = readShortUnsigned(buffer); - - // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901123 - if (connection.isSupported(MqttVersion.MQTT_5) && buffer.hasRemaining()) { - reasonCode = PublishAckReasonCode.ofValue(readByteUnsigned(buffer)); - } - } - - @Override - protected boolean isPropertiesSupported(MqttConnection connection, ByteBuffer buffer) { - return connection.isSupported(MqttVersion.MQTT_5) && buffer.hasRemaining(); - } - - @Override - protected Set getAvailableProperties() { - return AVAILABLE_PROPERTIES; - } - - @Override - protected void applyProperty(PacketProperty property, String value) { - switch (property) { - case REASON_STRING: - reason = value; - break; - default: - unexpectedProperty(property); - } - } -} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/in/PublishCompleteInPacket.java b/network/src/main/java/javasabr/mqtt/network/packet/in/PublishCompleteInPacket.java deleted file mode 100644 index 1a4fc477..00000000 --- a/network/src/main/java/javasabr/mqtt/network/packet/in/PublishCompleteInPacket.java +++ /dev/null @@ -1,101 +0,0 @@ -package javasabr.mqtt.network.packet.in; - -import java.nio.ByteBuffer; -import java.util.EnumSet; -import java.util.Set; -import javasabr.mqtt.base.utils.DebugUtils; -import javasabr.mqtt.model.MqttVersion; -import javasabr.mqtt.model.PacketProperty; -import javasabr.mqtt.model.reason.code.PublishCompletedReasonCode; -import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.HasPacketId; -import javasabr.mqtt.network.packet.MqttPacketType; -import lombok.Getter; -import lombok.experimental.Accessors; - -/** - * Publish complete (QoS 2 delivery part 3). - */ -@Getter -@Accessors(fluent = true, chain = false) -public class PublishCompleteInPacket extends MqttReadablePacket implements HasPacketId { - - private static final byte PACKET_TYPE = (byte) MqttPacketType.PUBLISH_COMPLETED.ordinal(); - - static { - DebugUtils.registerIncludedFields("reasonCode", "packetId"); - } - - private static final Set AVAILABLE_PROPERTIES = EnumSet.of( - /* - Followed by the UTF-8 Encoded String representing the reason associated with this response. This - Reason String is human readable, designed for diagnostics and SHOULD NOT be parsed by the - receiver. - - The sender uses this value to give additional information to the receiver. The sender MUST NOT send - this Property if it would increase the size of the PUBREL packet beyond the Maximum Packet Size - specified by the receiver [MQTT-3.6.2-2]. It is a Protocol Error to include the Reason String more than - once. - */ - PacketProperty.REASON_STRING, - /* - Followed by UTF-8 String Pair. This property can be used to provide additional diagnostic or other - information for the PUBREL. The sender MUST NOT send this property if it would increase the size of the - PUBREL packet beyond the Maximum Packet Size specified by the receiver [MQTT-3.6.2-3]. The User - Property is allowed to appear multiple times to represent multiple name, value pairs. The same name is - allowed to appear more than once - */ - PacketProperty.USER_PROPERTY); - - private PublishCompletedReasonCode reasonCode; - private int packetId; - - // properties - private String reason; - - public PublishCompleteInPacket(byte info) { - super(info); - this.reasonCode = PublishCompletedReasonCode.SUCCESS; - this.reason = ""; - } - - @Override - public byte packetType() { - return PACKET_TYPE; - } - - @Override - protected void readVariableHeader(MqttConnection connection, ByteBuffer buffer) { - super.readVariableHeader(connection, buffer); - - // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718083 - packetId = readShortUnsigned(buffer); - - // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901154 - if (connection.isSupported(MqttVersion.MQTT_5) && buffer.hasRemaining()) { - reasonCode = PublishCompletedReasonCode.of(readByteUnsigned(buffer)); - } - } - - @Override - protected boolean isPropertiesSupported(MqttConnection connection, ByteBuffer buffer) { - // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901154 - return super.isPropertiesSupported(connection, buffer) && buffer.hasRemaining(); - } - - @Override - protected Set getAvailableProperties() { - return AVAILABLE_PROPERTIES; - } - - @Override - protected void applyProperty(PacketProperty property, String value) { - switch (property) { - case REASON_STRING: - reason = value; - break; - default: - unexpectedProperty(property); - } - } -} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/in/PublishInPacket.java b/network/src/main/java/javasabr/mqtt/network/packet/in/PublishInPacket.java deleted file mode 100644 index 5fadbba8..00000000 --- a/network/src/main/java/javasabr/mqtt/network/packet/in/PublishInPacket.java +++ /dev/null @@ -1,358 +0,0 @@ -package javasabr.mqtt.network.packet.in; - -import static javasabr.mqtt.model.utils.TopicUtils.EMPTY_TOPIC_NAME; -import static javasabr.mqtt.model.utils.TopicUtils.buildTopicName; - -import java.nio.ByteBuffer; -import java.util.EnumSet; -import java.util.Set; -import javasabr.mqtt.base.utils.DebugUtils; -import javasabr.mqtt.model.MqttProperties; -import javasabr.mqtt.model.PacketProperty; -import javasabr.mqtt.model.QoS; -import javasabr.mqtt.model.topic.TopicName; -import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.MqttPacketType; -import javasabr.rlib.collections.array.ArrayFactory; -import javasabr.rlib.collections.array.IntArray; -import javasabr.rlib.collections.array.MutableIntArray; -import javasabr.rlib.common.util.ArrayUtils; -import javasabr.rlib.common.util.NumberUtils; -import javasabr.rlib.common.util.StringUtils; -import lombok.Getter; - -/** - * Publish message. - */ -@Getter -public class PublishInPacket extends MqttReadablePacket { - - private static final byte PACKET_TYPE = (byte) MqttPacketType.PUBLISH.ordinal(); - - static { - DebugUtils.registerIncludedFields("topicName", "qos", "duplicate", "packetId"); - } - - private static final Set AVAILABLE_PROPERTIES = EnumSet.of( - /* - Followed by the value of the Payload Format Indicator, either of: - • 0 (0x00) Byte Indicates that the Payload is unspecified bytes, which is equivalent to not sending a - Payload Format Indicator. - • 1 (0x01) Byte Indicates that the Payload is UTF-8 Encoded Character Data. The UTF-8 data in - the Payload MUST be well-formed UTF-8 as defined by the Unicode specification [Unicode] - and restated in RFC 3629 [RFC3629]. - - A Server MUST send the Payload Format Indicator unaltered to all subscribers receiving the Application - 1563 Message [MQTT-3.3.2-4]. The receiver MAY validate that the Payload is of the format indicated, and if it - is not send a PUBACK, PUBREC, or DISCONNECT with Reason Code of 0x99 (Payload format invalid) - as described in section 4.13. Refer to section 5.4.9 for information about security issues in validating the - payload format. - */ - PacketProperty.PAYLOAD_FORMAT_INDICATOR, - /* - Followed by the Four Byte Integer representing the Message Expiry Interval. - - If present, the Four Byte value is the lifetime of the Application Message in seconds. If the Message - Expiry Interval has passed and the Server has not managed to start onward delivery to a matching - subscriber, then it MUST delete the copy of the message for that subscriber [MQTT-3.3.2-5]. - - If absent, the Application Message does not expire. - - The PUBLISH packet sent to a Client by the Server MUST contain a Message Expiry Interval set to the - received value minus the time that the Application Message has been waiting in the Server [MQTT-3.3.2- - 6]. Refer to section 4.1 for details and limitations of stored state. - */ - PacketProperty.MESSAGE_EXPIRY_INTERVAL, - /* - Followed by the Two Byte integer representing the Topic Alias value. It is a Protocol Error to include the - Topic Alias value more than once. - - A Topic Alias is an integer value that is used to identify the Topic instead of using the Topic Name. This - reduces the size of the PUBLISH packet, and is useful when the Topic Names are long and the same - Topic Names are used repetitively within a Network Connection. - - The sender decides whether to use a Topic Alias and chooses the value. It sets a Topic Alias mapping by - including a non-zero length Topic Name and a Topic Alias in the PUBLISH packet. The receiver - processes the PUBLISH as normal but also sets the specified Topic Alias mapping to this Topic Name. - - If a Topic Alias mapping has been set at the receiver, a sender can send a PUBLISH packet that contains - that Topic Alias and a zero length Topic Name. The receiver then treats the incoming PUBLISH as if it - had contained the Topic Name of the Topic Alias. - - A sender can modify the Topic Alias mapping by sending another PUBLISH in the same Network - Connection with the same Topic Alias value and a different non-zero length Topic Name. - - Topic Alias mappings exist only within a Network Connection and last only for the lifetime of that Network - Connection. A receiver MUST NOT carry forward any Topic Alias mappings from one Network - Connection to another [MQTT-3.3.2-7]. - - A Topic Alias of 0 is not permitted. A sender MUST NOT send a PUBLISH packet containing a Topic - Alias which has the value 0 [MQTT-3.3.2-8]. - - A Client MUST NOT send a PUBLISH packet with a Topic Alias greater than the Topic Alias Maximum - value returned by the Server in the CONNACK packet [MQTT-3.3.2-9]. A Client MUST accept all Topic - Alias values greater than 0 and less than or equal to the Topic Alias Maximum value that it sent in the - CONNECT packet [MQTT-3.3.2-10]. - - A Server MUST NOT send a PUBLISH packet with a Topic Alias greater than the Topic Alias Maximum - value sent by the Client in the CONNECT packet [MQTT-3.3.2-11]. A Server MUST accept all Topic Alias - values greater than 0 and less than or equal to the Topic Alias Maximum value that it returned in the - CONNACK packet [MQTT-3.3.2-12]. - - The Topic Alias mappings used by the Client and Server are independent from each other. Thus, when a - Client sends a PUBLISH containing a Topic Alias value of 1 to a Server and the Server sends a PUBLISH - with a Topic Alias value of 1 to that Client they will in general be referring to different Topics. - */ - PacketProperty.TOPIC_ALIAS, - /* - Followed by a UTF-8 Encoded String which is used as the Topic Name for a response message. The - Response Topic MUST be a UTF-8 Encoded String as defined in section 1.5.4 [MQTT-3.3.2-13]. The - Response Topic MUST NOT contain wildcard characters [MQTT-3.3.2-14]. It is a Protocol Error to include - the Response Topic more than once. The presence of a Response Topic identifies the Message as a - Request. - - Refer to section 4.10 for more information about Request / Response. - - The Server MUST send the Response Topic unaltered to all subscribers receiving the Application - Message [MQTT-3.3.2-15]. - */ - PacketProperty.RESPONSE_TOPIC, - /* - Followed by Binary Data. The Correlation Data is used by the sender of the Request Message to identify - which request the Response Message is for when it is received. It is a Protocol Error to include - Correlation Data more than once. If the Correlation Data is not present, the Requester does not require - any correlation data. - - The Server MUST send the Correlation Data unaltered to all subscribers receiving the Application - Message [MQTT-3.3.2-16]. The value of the Correlation Data only has meaning to the sender of the - Request Message and receiver of the Response Message. - */ - PacketProperty.CORRELATION_DATA, - /* - Followed by a UTF-8 String Pair. The User Property is allowed to appear multiple times to represent - multiple name, value pairs. The same name is allowed to appear more than once. - - The Server MUST send all User Properties unaltered in a PUBLISH packet when forwarding the - Application Message to a Client [MQTT-3.3.2-17]. The Server MUST maintain the order of User - Properties when forwarding the Application Message [MQTT-3.3.2-18]. - */ - PacketProperty.USER_PROPERTY, - /* - Followed by a Variable Byte Integer representing the identifier of the subscription. - - The Subscription Identifier can have the value of 1 to 268,435,455. It is a Protocol Error if the - Subscription Identifier has a value of 0. Multiple Subscription Identifiers will be included if the - publication - is the result of a match to more than one subscription, in this case their order is not significant. - */ - PacketProperty.SUBSCRIPTION_IDENTIFIER, - /* - Followed by a UTF-8 Encoded String describing the content of the Application Message. The Content - Type MUST be a UTF-8 Encoded String as defined in section 1.5.4 [MQTT-3.3.2-19]. - It is a Protocol Error to include the Content Type more than once. The value of the Content Type is - defined by the sending and receiving application. - - A Server MUST send the Content Type unaltered to all subscribers receiving the Application Message - [MQTT-3.3.2-20]. - */ - PacketProperty.CONTENT_TYPE); - - /** - * This field indicates the level of assurance for delivery of an Application Message. The QoS levels are shown - * below. - *

- * 0 - 00 At most once delivery 1 --01 At least once delivery 2 - 10 Exactly once delivery - - 11 Reserved – must not - * be used - *

- * If the Server included a Maximum QoS in its CONNACK response to a Client and it receives a PUBLISH packet with a - * QoS greater than this, then it uses DISCONNECT with Reason Code 0x9B (QoS not supported) as described in section - * 4.13 Handling errors. - *

- * A PUBLISH Packet MUST NOT have both QoS bits set to 1 [MQTT-3.3.1-4]. If a Server or Client receives a PUBLISH - * packet which has both QoS bits set to 1 it is a Malformed Packet. Use DISCONNECT with Reason Code 0x81 (Malformed - * Packet) as described in - */ - private final QoS qos; - - /** - * If the DUP flag is set to 0, it indicates that this is the first occasion that the Client or Server has attempted - * to send this PUBLISH packet. If the DUP flag is set to 1, it indicates that this might be re-delivery of an earlier - * attempt to send the packet. - *

- * The DUP flag MUST be set to 1 by the Client or Server when it attempts to re-deliver a PUBLISH packet - * [MQTT-3.3.1-1]. The DUP flag MUST be set to 0 for all QoS 0 messages [MQTT-3.3.1-2]. - *

- * The value of the DUP flag from an incoming PUBLISH packet is not propagated when the PUBLISH packet is sent to - * subscribers by the Server. The DUP flag in the outgoing PUBLISH packet is set independently to the incoming PUBLISH - * packet, its value MUST be determined solely by whether the outgoing PUBLISH packet is a retransmission - */ - private final boolean duplicate; - - /** - * If the RETAIN flag is set to 1 in a PUBLISH packet sent by a Client to a Server, the Server MUST replace any - * existing retained message for this topic and store the Application Message [MQTT-3.3.1-5], so that it can be - * delivered to future subscribers whose subscriptions match its Topic Name. If the Payload contains zero bytes it is - * processed normally by the Server but any retained message with the same topic name MUST be removed and any future - * subscribers for the topic will not receive a retained message [MQTT1476 3.3.1-6]. A retained message with a Payload - * containing zero bytes MUST NOT be stored as a retained message on the Server [MQTT-3.3.1-7]. - *

- * If the RETAIN flag is 0 in a PUBLISH packet sent by a Client to a Server, the Server MUST NOT store the message as - * a retained message and MUST NOT remove or replace any existing retained message [MQTT-3.3.1-8]. - *

- * If the Server included Retain Available in its CONNACK response to a Client with its value set to 0 and it receives - * a PUBLISH packet with the RETAIN flag is set to 1, then it uses the DISCONNECT Reason Code of 0x9A (Retain not - * supported) as described in section 4.13. - *

- * When a new Non-shared Subscription is made, the last retained message, if any, on each matching topic name is sent - * to the Client as directed by the Retain Handling Subscription Option. These messages are sent with the RETAIN flag - * set to 1. Which retained messages are sent is controlled by the Retain Handling Subscription Option. At the time of - * the Subscription: • If Retain Handling is set to 0 the Server MUST send the retained messages matching the Topic - * Filter of the subscription to the Client [MQTT-3.3.1-9]. • If Retain Handling is set to 1 then if the subscription - * did not already exist, the Server MUST send all retained message matching the Topic Filter of the subscription to - * the Client, and if the subscription did exist the Server MUST NOT send the retained messages. [MQTT-3.3.1-10]. • If - * Retain Handling is set to 2, the Server MUST NOT send the retained messages - *

- * If the Server receives a PUBLISH packet with the RETAIN flag set to 1, and QoS 0 it SHOULD store the new QoS 0 - * message as the new retained message for that topic, but MAY choose to discard it at any time. If this happens there - * will be no retained message for that topic. - *

- * If the current retained message for a Topic expires, it is discarded and there will be no retained message for that - * topic. - *

- * The setting of the RETAIN flag in an Application Message forwarded by the Server from an established connection is - * controlled by the Retain As Published subscription option. Refer to section 3.8.3.1 for a definition of the - * Subscription Options. • If the value of Retain As Published subscription option is set to 0, the Server MUST set - * the RETAIN flag to 0 when forwarding an Application Message regardless of how the RETAIN flag was set in the - * received PUBLISH packet [MQTT-3.3.1-12]. • If the value of Retain As Published subscription option is set to 1, the - * Server MUST set the RETAIN flag equal to the RETAIN flag in the received PUBLISH packet - */ - private final boolean retained; - - /** - * The Topic Name identifies the information channel to which Payload data is published. - *

- * The Topic Name MUST be present as the first field in the PUBLISH packet Variable Header. It MUST be a UTF-8 Encoded - * String as defined in section 1.5.4 [MQTT-3.3.2-1]. - *

- * Standards Track Work Product Copyright © OASIS Open 2019. All Rights Reserved. Page 56 of 137 The Topic Name in the - * PUBLISH packet MUST NOT contain wildcard characters [MQTT-3.3.2-2]. - *

- * The Topic Name in a PUBLISH packet sent by a Server to a subscribing Client MUST match the Subscription’s Topic - * Filter according to the matching process defined in section 4.7 [MQTT-3.3.2-3]. However, as the Server is permitted - * to map the Topic Name to another name, it might not be the same as the Topic Name in the original PUBLISH packet. - *

- * To reduce the size of the PUBLISH packet the sender can use a Topic Alias. The Topic Alias is described in section - * 3.3.2.3.4. It is a Protocol Error if the Topic Name is zero length and there is no Topic Alias. - */ - private TopicName topicName; - - /** - * The Packet Identifier field is only present in PUBLISH packets where the QoS level is 1 or 2. Section 2.2.1 - * provides more information about Packet Identifiers. - */ - private int packetId; - - private byte[] payload; - - // properties - private String responseTopic; - private String contentType; - - private IntArray subscriptionIds; - - private byte[] correlationData; - - private long messageExpiryInterval = MqttProperties.MESSAGE_EXPIRY_INTERVAL_UNDEFINED; - private int topicAlias = MqttProperties.TOPIC_ALIAS_DEFAULT; - private boolean payloadFormatIndicator = MqttProperties.PAYLOAD_FORMAT_INDICATOR_DEFAULT; - - public PublishInPacket(byte info) { - super(info); - this.qos = QoS.of((info >> 1) & 0x03); - this.retained = NumberUtils.isSetBit(info, 0); - this.duplicate = NumberUtils.isSetBit(info, 3); - this.topicName = EMPTY_TOPIC_NAME; - this.responseTopic = StringUtils.EMPTY; - this.contentType = StringUtils.EMPTY; - this.correlationData = ArrayUtils.EMPTY_BYTE_ARRAY; - this.payload = ArrayUtils.EMPTY_BYTE_ARRAY; - this.subscriptionIds = IntArray.empty(); - } - - @Override - public byte packetType() { - return PACKET_TYPE; - } - - @Override - protected void readVariableHeader(MqttConnection connection, ByteBuffer buffer) { - // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718039 - topicName = buildTopicName(readString(buffer, Integer.MAX_VALUE)); - packetId = qos != QoS.AT_MOST_ONCE ? readShortUnsigned(buffer) : 0; - } - - @Override - protected void readPayload(MqttConnection connection, ByteBuffer buffer) { - // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718040 - payload = readPayload(buffer); - } - - @Override - protected Set getAvailableProperties() { - return AVAILABLE_PROPERTIES; - } - - @Override - protected void applyProperty(PacketProperty property, long value) { - switch (property) { - case PAYLOAD_FORMAT_INDICATOR: - payloadFormatIndicator = NumberUtils.toBoolean(value); - break; - case TOPIC_ALIAS: - topicAlias = NumberUtils.validate( - (int) value, - MqttProperties.TOPIC_ALIAS_MIN, - MqttProperties.TOPIC_ALIAS_MAX); - break; - case MESSAGE_EXPIRY_INTERVAL: - messageExpiryInterval = value; - break; - case SUBSCRIPTION_IDENTIFIER: - if (subscriptionIds == IntArray.empty()) { - subscriptionIds = ArrayFactory.mutableIntArray(); - } - if (subscriptionIds instanceof MutableIntArray array) { - array.add((int) value); - } - break; - default: - unexpectedProperty(property); - } - } - - @Override - protected void applyProperty(PacketProperty property, String value) { - switch (property) { - case RESPONSE_TOPIC: - // TODO should be validated - responseTopic = value; - break; - case CONTENT_TYPE: - contentType = value; - break; - default: - unexpectedProperty(property); - } - } - - @Override - protected void applyProperty(PacketProperty property, byte[] value) { - switch (property) { - case CORRELATION_DATA: - correlationData = value; - break; - default: - unexpectedProperty(property); - } - } -} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/in/PublishReceivedInPacket.java b/network/src/main/java/javasabr/mqtt/network/packet/in/PublishReceivedInPacket.java deleted file mode 100644 index 561956f2..00000000 --- a/network/src/main/java/javasabr/mqtt/network/packet/in/PublishReceivedInPacket.java +++ /dev/null @@ -1,102 +0,0 @@ -package javasabr.mqtt.network.packet.in; - -import java.nio.ByteBuffer; -import java.util.EnumSet; -import java.util.Set; -import javasabr.mqtt.base.utils.DebugUtils; -import javasabr.mqtt.model.MqttVersion; -import javasabr.mqtt.model.PacketProperty; -import javasabr.mqtt.model.reason.code.PublishReceivedReasonCode; -import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.HasPacketId; -import javasabr.mqtt.network.packet.MqttPacketType; -import javasabr.rlib.common.util.StringUtils; -import lombok.Getter; -import lombok.experimental.Accessors; - -/** - * Publish received (QoS 2 delivery part 1). - */ -@Getter -@Accessors(fluent = true, chain = false) -public class PublishReceivedInPacket extends MqttReadablePacket implements HasPacketId { - - private static final byte PACKET_TYPE = (byte) MqttPacketType.PUBLISH_RECEIVED.ordinal(); - - static { - DebugUtils.registerIncludedFields("reasonCode", "packetId"); - } - - private static final Set AVAILABLE_PROPERTIES = EnumSet.of( - /* - Followed by the UTF-8 Encoded String representing the reason associated with this response. This - Reason String is human readable, designed for diagnostics and SHOULD NOT be parsed by the - receiver. - - The sender uses this value to give additional information to the receiver. The sender MUST NOT send - this Property if it would increase the size of the PUBREL packet beyond the Maximum Packet Size - specified by the receiver [MQTT-3.6.2-2]. It is a Protocol Error to include the Reason String more than - once. - */ - PacketProperty.REASON_STRING, - /* - Followed by UTF-8 String Pair. This property can be used to provide additional diagnostic or other - information for the PUBREL. The sender MUST NOT send this property if it would increase the size of the - PUBREL packet beyond the Maximum Packet Size specified by the receiver [MQTT-3.6.2-3]. The User - Property is allowed to appear multiple times to represent multiple name, value pairs. The same name is - allowed to appear more than once - */ - PacketProperty.USER_PROPERTY); - - private PublishReceivedReasonCode reasonCode; - private int packetId; - - // properties - private String reason; - - public PublishReceivedInPacket(byte info) { - super(info); - this.reasonCode = PublishReceivedReasonCode.SUCCESS; - this.reason = StringUtils.EMPTY; - } - - @Override - protected void readVariableHeader(MqttConnection connection, ByteBuffer buffer) { - super.readVariableHeader(connection, buffer); - - // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718050 - packetId = readShortUnsigned(buffer); - - // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901143 - if (connection.isSupported(MqttVersion.MQTT_5) && buffer.hasRemaining()) { - reasonCode = PublishReceivedReasonCode.ofValue(readByteUnsigned(buffer)); - } - } - - @Override - protected boolean isPropertiesSupported(MqttConnection connection, ByteBuffer buffer) { - // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901144 - return super.isPropertiesSupported(connection, buffer) && buffer.hasRemaining(); - } - - @Override - public byte packetType() { - return PACKET_TYPE; - } - - @Override - protected Set getAvailableProperties() { - return AVAILABLE_PROPERTIES; - } - - @Override - protected void applyProperty(PacketProperty property, String value) { - switch (property) { - case REASON_STRING: - reason = value; - break; - default: - unexpectedProperty(property); - } - } -} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/in/PublishReleaseInPacket.java b/network/src/main/java/javasabr/mqtt/network/packet/in/PublishReleaseInPacket.java deleted file mode 100644 index 2a6ec02e..00000000 --- a/network/src/main/java/javasabr/mqtt/network/packet/in/PublishReleaseInPacket.java +++ /dev/null @@ -1,101 +0,0 @@ -package javasabr.mqtt.network.packet.in; - -import java.nio.ByteBuffer; -import java.util.EnumSet; -import java.util.Set; -import javasabr.mqtt.base.utils.DebugUtils; -import javasabr.mqtt.model.MqttVersion; -import javasabr.mqtt.model.PacketProperty; -import javasabr.mqtt.model.reason.code.PublishReleaseReasonCode; -import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.HasPacketId; -import javasabr.mqtt.network.packet.MqttPacketType; -import lombok.Getter; -import lombok.experimental.Accessors; - -/** - * Publish release (QoS 2 delivery part 2). - */ -@Getter -@Accessors(fluent = true, chain = false) -public class PublishReleaseInPacket extends MqttReadablePacket implements HasPacketId { - - private static final byte PACKET_TYPE = (byte) MqttPacketType.PUBLISH_RELEASED.ordinal(); - - static { - DebugUtils.registerIncludedFields("reasonCode", "packetId"); - } - - private static final Set AVAILABLE_PROPERTIES = EnumSet.of( - /* - Followed by the UTF-8 Encoded String representing the reason associated with this response. This - Reason String is human readable, designed for diagnostics and SHOULD NOT be parsed by the - receiver. - - The sender uses this value to give additional information to the receiver. The sender MUST NOT send - this Property if it would increase the size of the PUBREL packet beyond the Maximum Packet Size - specified by the receiver [MQTT-3.6.2-2]. It is a Protocol Error to include the Reason String more than - once. - */ - PacketProperty.REASON_STRING, - /* - Followed by UTF-8 String Pair. This property can be used to provide additional diagnostic or other - information for the PUBREL. The sender MUST NOT send this property if it would increase the size of the - PUBREL packet beyond the Maximum Packet Size specified by the receiver [MQTT-3.6.2-3]. The User - Property is allowed to appear multiple times to represent multiple name, value pairs. The same name is - allowed to appear more than once - */ - PacketProperty.USER_PROPERTY); - - private PublishReleaseReasonCode reasonCode; - private int packetId; - - // properties - private String reason; - - public PublishReleaseInPacket(byte info) { - super(info); - this.reasonCode = PublishReleaseReasonCode.SUCCESS; - this.reason = ""; - } - - @Override - public byte packetType() { - return PACKET_TYPE; - } - - @Override - protected void readVariableHeader(MqttConnection connection, ByteBuffer buffer) { - super.readVariableHeader(connection, buffer); - - // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718055 - packetId = readShortUnsigned(buffer); - - // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901143 - if (connection.isSupported(MqttVersion.MQTT_5) && buffer.hasRemaining()) { - reasonCode = PublishReleaseReasonCode.of(readByteUnsigned(buffer)); - } - } - - @Override - protected boolean isPropertiesSupported(MqttConnection connection, ByteBuffer buffer) { - // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901143 - return super.isPropertiesSupported(connection, buffer) && buffer.hasRemaining(); - } - - @Override - protected Set getAvailableProperties() { - return AVAILABLE_PROPERTIES; - } - - @Override - protected void applyProperty(PacketProperty property, String value) { - switch (property) { - case REASON_STRING: - reason = value; - break; - default: - unexpectedProperty(property); - } - } -} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/in/SubscribeAckInPacket.java b/network/src/main/java/javasabr/mqtt/network/packet/in/SubscribeAckInPacket.java deleted file mode 100644 index 208a6c2e..00000000 --- a/network/src/main/java/javasabr/mqtt/network/packet/in/SubscribeAckInPacket.java +++ /dev/null @@ -1,94 +0,0 @@ -package javasabr.mqtt.network.packet.in; - -import java.nio.ByteBuffer; -import java.util.EnumSet; -import java.util.Set; -import javasabr.mqtt.model.PacketProperty; -import javasabr.mqtt.model.reason.code.SubscribeAckReasonCode; -import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.MqttPacketType; -import javasabr.rlib.collections.array.ArrayFactory; -import javasabr.rlib.collections.array.MutableArray; -import javasabr.rlib.common.util.StringUtils; -import lombok.Getter; - -/** - * Subscribe acknowledgement. - */ -@Getter -public class SubscribeAckInPacket extends MqttReadablePacket { - - private static final byte PACKET_TYPE = (byte) MqttPacketType.SUBSCRIBE_ACK.ordinal(); - - private static final Set AVAILABLE_PROPERTIES = EnumSet.of( - /* - Followed by the UTF-8 Encoded String representing the reason associated with this response. This - Reason String is a human readable string designed for diagnostics and SHOULD NOT be parsed by the - Client. - - The Server uses this value to give additional information to the Client. The Server MUST NOT send this - Property if it would increase the size of the SUBACK packet beyond the Maximum Packet Size specified - by the Client - */ - PacketProperty.REASON_STRING, - /* - Followed by UTF-8 String Pair. This property can be used to provide additional diagnostic or other - information. The Server MUST NOT send this property if it would increase the size of the SUBACK packet - beyond the Maximum Packet Size specified by Client [MQTT-3.9.2-2]. The User Property is allowed to - appear multiple times to represent multiple name, value pairs. The same name is allowed to appear more - than once. - */ - PacketProperty.USER_PROPERTY); - - private MutableArray reasonCodes; - private int packetId; - - // properties - private String reason; - - public SubscribeAckInPacket(byte info) { - super(info); - this.reasonCodes = ArrayFactory.mutableArray(SubscribeAckReasonCode.class); - this.reason = StringUtils.EMPTY; - } - - @Override - public byte packetType() { - return PACKET_TYPE; - } - - @Override - protected void readVariableHeader(MqttConnection connection, ByteBuffer buffer) { - // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718070 - packetId = readShortUnsigned(buffer); - } - - @Override - protected void readPayload(MqttConnection connection, ByteBuffer buffer) { - - // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718071 - if (buffer.remaining() < 1) { - throw new IllegalStateException("No any topic filters."); - } - - while (buffer.hasRemaining()) { - reasonCodes.add(SubscribeAckReasonCode.of(readByteUnsigned(buffer))); - } - } - - @Override - protected Set getAvailableProperties() { - return AVAILABLE_PROPERTIES; - } - - @Override - protected void applyProperty(PacketProperty property, String value) { - switch (property) { - case REASON_STRING: - reason = value; - break; - default: - unexpectedProperty(property); - } - } -} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/in/SubscribeInPacket.java b/network/src/main/java/javasabr/mqtt/network/packet/in/SubscribeInPacket.java deleted file mode 100644 index 508de457..00000000 --- a/network/src/main/java/javasabr/mqtt/network/packet/in/SubscribeInPacket.java +++ /dev/null @@ -1,120 +0,0 @@ -package javasabr.mqtt.network.packet.in; - -import static javasabr.mqtt.model.utils.TopicUtils.buildTopicFilter; - -import java.nio.ByteBuffer; -import java.util.EnumSet; -import java.util.Set; -import javasabr.mqtt.base.utils.DebugUtils; -import javasabr.mqtt.model.MqttProperties; -import javasabr.mqtt.model.MqttVersion; -import javasabr.mqtt.model.PacketProperty; -import javasabr.mqtt.model.QoS; -import javasabr.mqtt.model.SubscribeRetainHandling; -import javasabr.mqtt.model.subscriber.SubscribeTopicFilter; -import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.MqttPacketType; -import javasabr.rlib.collections.array.ArrayFactory; -import javasabr.rlib.collections.array.MutableArray; -import javasabr.rlib.common.util.NumberUtils; -import lombok.Getter; - -/** - * Subscribe request. - */ -@Getter -public class SubscribeInPacket extends MqttReadablePacket { - - private static final byte PACKET_TYPE = (byte) MqttPacketType.SUBSCRIBE.ordinal(); - - static { - DebugUtils.registerIncludedFields("packetId", "topicFilters"); - } - - private static final Set AVAILABLE_PROPERTIES = EnumSet.of( - /* - Followed by a Variable Byte Integer representing the identifier of the subscription. The Subscription - Identifier can have the value of 1 to 268,435,455. It is a Protocol Error if the Subscription Identifier has a - value of 0. It is a Protocol Error to include the Subscription Identifier more than once. - - The Subscription Identifier is associated with any subscription created or modified as the result of this - SUBSCRIBE packet. If there is a Subscription Identifier, it is stored with the subscription. If this - property is - not specified, then the absence of a Subscription Identifier is stored with the subscription. - */ - PacketProperty.SUBSCRIPTION_IDENTIFIER, - /* - The User Property is allowed to appear multiple times to represent multiple name, value pairs. The same - name is allowed to appear more than once. - */ - PacketProperty.USER_PROPERTY); - - private MutableArray topicFilters; - private int packetId; - - // properties - private int subscriptionId; - - public SubscribeInPacket(byte info) { - super(info); - this.topicFilters = ArrayFactory.mutableArray(SubscribeTopicFilter.class); - this.subscriptionId = MqttProperties.SUBSCRIPTION_ID_UNDEFINED; - } - - @Override - public byte packetType() { - return PACKET_TYPE; - } - - @Override - protected void readVariableHeader(MqttConnection connection, ByteBuffer buffer) { - // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718065 - packetId = readShortUnsigned(buffer); - } - - @Override - protected void readPayload(MqttConnection connection, ByteBuffer buffer) { - - if (buffer.remaining() < 1) { - throw new IllegalStateException("No any topic filters."); - } - - boolean isMqtt5 = connection.isSupported(MqttVersion.MQTT_5); - - // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718066 - // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901168 - while (buffer.hasRemaining()) { - - var topicFilter = readString(buffer, Integer.MAX_VALUE); - var options = readByteUnsigned(buffer); - - var qos = QoS.of(options & 0x03); - var retainHandling = isMqtt5 ? SubscribeRetainHandling.of((options >> 4) & 0x03) : SubscribeRetainHandling.SEND; - - if (qos == QoS.INVALID || retainHandling == SubscribeRetainHandling.INVALID) { - throw new IllegalStateException("Unsupported qos or retain handling"); - } - - var noLocal = !isMqtt5 || NumberUtils.isSetBit(options, 2); - var rap = !isMqtt5 || NumberUtils.isSetBit(options, 3); - - topicFilters.add(new SubscribeTopicFilter(buildTopicFilter(topicFilter), qos, retainHandling, noLocal, rap)); - } - } - - @Override - protected Set getAvailableProperties() { - return AVAILABLE_PROPERTIES; - } - - @Override - protected void applyProperty(PacketProperty property, long value) { - switch (property) { - case SUBSCRIPTION_IDENTIFIER: - subscriptionId = (int) value; - break; - default: - unexpectedProperty(property); - } - } -} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/Connect5OutPacket.java b/network/src/main/java/javasabr/mqtt/network/packet/out/Connect5OutPacket.java deleted file mode 100644 index 036a508b..00000000 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/Connect5OutPacket.java +++ /dev/null @@ -1,302 +0,0 @@ -package javasabr.mqtt.network.packet.out; - -import java.nio.ByteBuffer; -import java.util.EnumSet; -import java.util.Set; -import javasabr.mqtt.model.MqttProperties; -import javasabr.mqtt.model.MqttVersion; -import javasabr.mqtt.model.PacketProperty; -import javasabr.mqtt.model.QoS; -import javasabr.mqtt.model.data.type.StringPair; -import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.utils.MqttDataUtils; -import javasabr.rlib.collections.array.Array; -import javasabr.rlib.common.util.ArrayUtils; -import javasabr.rlib.common.util.StringUtils; - -/** - * Connect request. - */ -public class Connect5OutPacket extends Connect311OutPacket { - - private static final Set AVAILABLE_PROPERTIES = EnumSet.of( - /* - If the Session Expiry Interval is absent the value 0 is used. If it is set to 0, - or is absent, the Session ends when the Network Connection is closed. - If the Session Expiry Interval is 0xFFFFFFFF (UINT_MAX), the Session does not expire. - - The Client and Server MUST store the Session State after the Network Connection is closed if the - Session Expiry Interval is greater than 0 - */ - PacketProperty.SESSION_EXPIRY_INTERVAL, - /* - Followed by the Two Byte Integer representing the Receive Maximum value. It is a Protocol Error to - include the Receive Maximum value more than once or for it to have the value 0. - - The Client uses this value to limit the number of QoS 1 and QoS 2 publications that it is willing to process - concurrently. There is no mechanism to limit the QoS 0 publications that the Server might try to send. - - The value of Receive Maximum applies only to the current Network Connection. If the Receive Maximum - value is absent then its value defaults to 65,535. - */ - PacketProperty.RECEIVE_MAXIMUM_PUBLISH, - /* - Followed by a Four Byte Integer representing the Maximum Packet Size the Client is willing to accept. If - the Maximum Packet Size is not present, no limit on the packet size is imposed beyond the limitations in - the protocol as a result of the remaining length encoding and the protocol header sizes. - - It is a Protocol Error to include the Maximum Packet Size more than once, or for the value to be set to - zero. - */ - PacketProperty.MAXIMUM_PACKET_SIZE, - /* - Followed by the Two Byte Integer representing the Topic Alias Maximum value. It is a Protocol Error to - include the Topic Alias Maximum value more than once. If the Topic Alias Maximum property is absent, - the default value is 0. - - This value indicates the highest value that the Client will accept as a Topic Alias sent by the Server. The - Client uses this value to limit the number of Topic Aliases that it is willing to hold on this Connection. The - Server MUST NOT send a Topic Alias in a PUBLISH packet to the Client greater than Topic Alias - Maximum [MQTT-3.1.2-26]. A value of 0 indicates that the Client does not accept any Topic Aliases on - this connection. If Topic Alias Maximum is absent or zero, the Server MUST NOT send any Topic Aliases - to the Client [MQTT-3.1.2-27]. - */ - PacketProperty.TOPIC_ALIAS_MAXIMUM, - /* - Followed by a Byte with a value of either 0 or 1. It is Protocol Error to include the Request Response - Information more than once, or to have a value other than 0 or 1. If the Request Response Information is - absent, the value of 0 is used. - - The Client uses this value to request the Server to return Response Information in the CONNACK. A - value of 0 indicates that the Server MUST NOT return Response Information [MQTT-3.1.2-28]. If the - value is 1 the Server MAY return Response Information in the CONNACK packet. - */ - PacketProperty.REQUEST_RESPONSE_INFORMATION, - /* - Followed by a Byte with a value of either 0 or 1. It is a Protocol Error to include Request Problem - Information more than once, or to have a value other than 0 or 1. If the Request Problem Information is - 8absent, the value of 1 is used. - - The Client uses this value to indicate whether the Reason String or User Properties are sent in the case - of failures. - - If the value of Request Problem Information is 0, the Server MAY return a Reason String or User - Properties on a CONNACK or DISCONNECT packet, but MUST NOT send a Reason String or User - Properties on any packet other than PUBLISH, CONNACK, or DISCONNECT [MQTT-3.1.2-29]. If the - value is 0 and the Client receives a Reason String or User Properties in a packet other than PUBLISH, - CONNACK, or DISCONNECT, it uses a DISCONNECT packet with Reason Code 0x82 (Protocol Error) - as described in section 4.13 Handling errors. - - If this value is 1, the Server MAY return a Reason String or User Properties on any packet where it is - allowed. - */ - PacketProperty.REQUEST_PROBLEM_INFORMATION, - /* - The User Property is allowed to appear multiple times to represent multiple name, value pairs. The same - name is allowed to appear more than once - */ - PacketProperty.USER_PROPERTY, - /* - Followed by a UTF-8 Encoded String containing the name of the authentication method used for - extended authentication .It is a Protocol Error to include Authentication Method more than once. - If Authentication Method is absent, extended authentication is not performed. Refer to section 4.12. - - If a Client sets an Authentication Method in the CONNECT, the Client MUST NOT send any packets other - than AUTH or DISCONNECT packets until it has received a CONNACK packet - */ - PacketProperty.AUTHENTICATION_METHOD, - /* - Followed by Binary Data containing authentication data. It is a Protocol Error to include Authentication - Data if there is no Authentication Method. It is a Protocol Error to include Authentication Data more than - once. - - The contents of this data are defined by the authentication method. Refer to section 4.12 for more - information about extended authentication. - */ - PacketProperty.AUTHENTICATION_DATA); - - private static final Set WILL_PROPERTIES = EnumSet.of( - /* - Followed by the Four Byte Integer representing the Will Delay Interval in seconds. It is a Protocol Error to - include the Will Delay Interval more than once. If the Will Delay Interval is absent, the default value is 0 - and there is no delay before the Will Message is published. - - The Server delays publishing the Client’s Will Message until the Will Delay Interval has passed or the - Session ends, whichever happens first. If a new Network Connection to this Session is made before the - Will Delay Interval has passed, the Server MUST NOT send the Will Message - */ - PacketProperty.WILL_DELAY_INTERVAL, - /* - Followed by the value of the Payload Format Indicator, either of: - • 0 (0x00) Byte Indicates that the Will Message is unspecified bytes, which is equivalent to not - sending a Payload Format Indicator. - • 1 (0x01) Byte Indicates that the Will Message is UTF-8 Encoded Character Data. The UTF-8 data - in the Payload MUST be well-formed UTF-8 as defined by the Unicode specification - [Unicode] and restated in RFC 3629 [RFC3629]. - - It is a Protocol Error to include the Payload Format Indicator more than once. The Server MAY validate - that the Will Message is of the format indicated, and if it is not se - */ - PacketProperty.PAYLOAD_FORMAT_INDICATOR, - /* - Followed by the Four Byte Integer representing the Message Expiry Interval. It is a Protocol Error to - include the Message Expiry Interval more than once. - - If present, the Four Byte value is the lifetime of the Will Message in seconds and is sent as the - Publication Expiry Interval when the Server publishes the Will Message. - - If absent, no Message Expiry Interval is sent when the Server publishes the Will Message. - */ - PacketProperty.MESSAGE_EXPIRY_INTERVAL, - /* - Followed by a UTF-8 Encoded String describing the content of the Will Message. It is a Protocol Error to - include the Content Type more than once. The value of the Content Type is defined by the sending and - receiving application. - */ - PacketProperty.CONTENT_TYPE, - /* - Followed by a UTF-8 Encoded String which is used as the Topic Name for a response message. It is a - Protocol Error to include the Response Topic more than once. The presence of a Response Topic - identifies the Will Message as a Request. - */ - PacketProperty.RESPONSE_TOPIC, - /* - Followed by Binary Data. The Correlation Data is used by the sender of the Request Message to identify - which request the Response Message is for when it is received. It is a Protocol Error to include - Correlation Data more than once. If the Correlation Data is not present, the Requester does not require - any correlation data. - - The value of the Correlation Data only has meaning to the sender of the Request Message and receiver - of the Response Message. - */ - PacketProperty.CORRELATION_DATA, - /* - Followed by a UTF-8 String Pair. The User Property is allowed to appear multiple times to represent - multiple name, value pairs. The same name is allowed to appear more than once. - - The Server MUST maintain the order of User Properties when publishing the Will Message - */ - PacketProperty.USER_PROPERTY); - - // properties - private final Array userProperties; - private final String authenticationMethod; - private final byte[] authenticationData; - - private final long sessionExpiryInterval; - private final int receiveMax; - private final int maximumPacketSize; - private final int topicAliasMaximum; - private final boolean requestResponseInformation; - private final boolean requestProblemInformation; - - public Connect5OutPacket(String clientId, int keepAlive) { - this( - StringUtils.EMPTY, - StringUtils.EMPTY, - clientId, - ArrayUtils.EMPTY_BYTE_ARRAY, - ArrayUtils.EMPTY_BYTE_ARRAY, - QoS.AT_MOST_ONCE, - keepAlive, - false, - false, - Array.empty(StringPair.class), - StringUtils.EMPTY, - ArrayUtils.EMPTY_BYTE_ARRAY, - MqttProperties.SESSION_EXPIRY_INTERVAL_UNDEFINED, - MqttProperties.RECEIVE_MAXIMUM_UNDEFINED, - MqttProperties.MAXIMUM_PACKET_SIZE_UNDEFINED, - MqttProperties.TOPIC_ALIAS_MAXIMUM_UNDEFINED, - false, - false); - } - - public Connect5OutPacket( - String username, - String willTopic, - String clientId, - byte[] password, - byte[] willPayload, - QoS willQos, - int keepAlive, - boolean willRetain, - boolean cleanStart, - Array userProperties, - String authenticationMethod, - byte[] authenticationData, - long sessionExpiryInterval, - int receiveMax, - int maximumPacketSize, - int topicAliasMaximum, - boolean requestResponseInformation, - boolean requestProblemInformation) { - super(username, willTopic, clientId, password, willPayload, willQos, keepAlive, willRetain, cleanStart); - this.userProperties = userProperties; - this.authenticationMethod = authenticationMethod; - this.authenticationData = authenticationData; - this.sessionExpiryInterval = sessionExpiryInterval; - this.receiveMax = receiveMax; - this.maximumPacketSize = maximumPacketSize; - this.topicAliasMaximum = topicAliasMaximum; - this.requestResponseInformation = requestResponseInformation; - this.requestProblemInformation = requestProblemInformation; - } - - protected MqttVersion getMqttVersion() { - return MqttVersion.MQTT_5; - } - - @Override - protected boolean isPropertiesSupported(MqttConnection connection) { - return true; - } - - @Override - protected void appendWillProperties(ByteBuffer buffer) { - - var propertiesBuffer = propertiesBuffer(); - - writeWillProperties(propertiesBuffer); - - if (propertiesBuffer.position() < 1) { - buffer.put((byte) 0); - return; - } - - propertiesBuffer.flip(); - - MqttDataUtils - .writeMbi(propertiesBuffer.limit(), buffer) - .put(propertiesBuffer); - } - - @Override - protected void writeProperties(MqttConnection connection, ByteBuffer buffer) { - // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901046 - writeStringPairProperties(buffer, PacketProperty.USER_PROPERTY, userProperties); - writeNotEmptyProperty(buffer, PacketProperty.AUTHENTICATION_METHOD, authenticationMethod); - writeNotEmptyProperty(buffer, PacketProperty.AUTHENTICATION_DATA, authenticationData); - writeProperty(buffer, PacketProperty.REQUEST_RESPONSE_INFORMATION, requestResponseInformation, false); - writeProperty(buffer, PacketProperty.REQUEST_PROBLEM_INFORMATION, requestProblemInformation, false); - writeProperty(buffer, PacketProperty.RECEIVE_MAXIMUM_PUBLISH, receiveMax, MqttProperties.RECEIVE_MAXIMUM_UNDEFINED); - writeProperty( - buffer, - PacketProperty.TOPIC_ALIAS_MAXIMUM, - topicAliasMaximum, - MqttProperties.TOPIC_ALIAS_MAXIMUM_UNDEFINED); - writeProperty( - buffer, - PacketProperty.SESSION_EXPIRY_INTERVAL, - sessionExpiryInterval, - MqttProperties.SESSION_EXPIRY_INTERVAL_UNDEFINED); - writeProperty( - buffer, - PacketProperty.MAXIMUM_PACKET_SIZE, - maximumPacketSize, - MqttProperties.MAXIMUM_PACKET_SIZE_UNDEFINED); - } - - protected void writeWillProperties(ByteBuffer buffer) { - } -} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/Disconnect311OutPacket.java b/network/src/main/java/javasabr/mqtt/network/packet/out/Disconnect311OutPacket.java deleted file mode 100644 index c35080ed..00000000 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/Disconnect311OutPacket.java +++ /dev/null @@ -1,22 +0,0 @@ -package javasabr.mqtt.network.packet.out; - -import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.MqttPacketType; - -/** - * Disconnect notification. - */ -public class Disconnect311OutPacket extends MqttWritablePacket { - - private static final byte PACKET_TYPE = (byte) MqttPacketType.DISCONNECT.ordinal(); - - @Override - public int expectedLength(MqttConnection connection) { - return 0; - } - - @Override - protected byte packetType() { - return PACKET_TYPE; - } -} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/PingRequest311OutPacket.java b/network/src/main/java/javasabr/mqtt/network/packet/out/PingRequest311OutPacket.java deleted file mode 100644 index 488d4863..00000000 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/PingRequest311OutPacket.java +++ /dev/null @@ -1,16 +0,0 @@ -package javasabr.mqtt.network.packet.out; - -import javasabr.mqtt.network.packet.MqttPacketType; - -/** - * PING request. - */ -public class PingRequest311OutPacket extends MqttWritablePacket { - - private static final byte PACKET_TYPE = (byte) MqttPacketType.PING_REQUEST.ordinal(); - - @Override - protected byte packetType() { - return PACKET_TYPE; - } -} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/PingResponse311OutPacket.java b/network/src/main/java/javasabr/mqtt/network/packet/out/PingResponse311OutPacket.java deleted file mode 100644 index ed8cc29c..00000000 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/PingResponse311OutPacket.java +++ /dev/null @@ -1,16 +0,0 @@ -package javasabr.mqtt.network.packet.out; - -import javasabr.mqtt.network.packet.MqttPacketType; - -/** - * PING response. - */ -public class PingResponse311OutPacket extends MqttWritablePacket { - - private static final byte PACKET_TYPE = (byte) MqttPacketType.PING_RESPONSE.ordinal(); - - @Override - protected byte packetType() { - return PACKET_TYPE; - } -} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/Publish5OutPacket.java b/network/src/main/java/javasabr/mqtt/network/packet/out/Publish5OutPacket.java deleted file mode 100644 index 0f239ddc..00000000 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/Publish5OutPacket.java +++ /dev/null @@ -1,192 +0,0 @@ -package javasabr.mqtt.network.packet.out; - -import java.nio.ByteBuffer; -import java.util.EnumSet; -import java.util.Set; -import javasabr.mqtt.base.utils.DebugUtils; -import javasabr.mqtt.model.MqttProperties; -import javasabr.mqtt.model.PacketProperty; -import javasabr.mqtt.model.QoS; -import javasabr.mqtt.model.data.type.StringPair; -import javasabr.mqtt.network.MqttConnection; -import javasabr.rlib.collections.array.Array; - -public class Publish5OutPacket extends Publish311OutPacket { - - static { - DebugUtils.registerIncludedFields("qos", "topicName", "duplicate"); - } - - private static final Set AVAILABLE_PROPERTIES = EnumSet.of( - /* - Followed by the value of the Payload Forma t Indicator, either of: - · 0 (0x00) Byte Indicates that the Payload is unspecified bytes, which is equivalent to not sending a - Payload Format Indicator. - · 1 (0x01) Byte Indicates that the Payload is UTF-8 Encoded Character Data. The UTF-8 data in the Payload - MUST be well-formed UTF-8 as defined by the Unicode specification [Unicode] and restated in RFC 3629 - [RFC3629]. - - A Server MUST send the Payload Format Indicator unaltered to all subscribers receiving the Application Message - [MQTT-3.3.2-4]. The receiver MAY validate that the Payload is of the format indicated, and if it is not send a - PUBACK, PUBREC, or DISCONNECT with Reason Code of 0x99 (Payload format invalid) as described in section 4.13. - Refer to section 5.4.9 for information about security issues in validating the payload format. - */ - PacketProperty.PAYLOAD_FORMAT_INDICATOR, - /* - Followed by the Four Byte Integer representing the Message Expiry Interval. - If present, the Four Byte value is the lifetime of the Application Message in seconds. If the Message Expiry - Interval has passed and the Server has not managed to start onward delivery to a matching subscriber, then it - MUST delete the copy of the message for that subscriber [MQTT-3.3.2-5]. - - If absent, the Application Message does not expire. - - The PUBLISH packet sent to a Client by the Server MUST contain a Message Expiry Interval set to the received - value minus the time that the Application Message has been waiting in the Server [MQTT-3.3.2-6]. Refer to - section 4.1 for details and limitations of stored state. - */ - PacketProperty.MESSAGE_EXPIRY_INTERVAL, - /* - Followed by the Two Byte integer representing the Topic Alias value. It is a Protocol Error to include the - Topic Alias value more than once. - - A Topic Alias is an integer value that is used to identify the Topic instead of using the Topic Name. This - reduces the size of the PUBLISH packet, and is useful when the Topic Names are long and the same Topic Names - are used repetitively within a Network Connection. - - The sender decides whether to use a Topic Alias and chooses the value. It sets a Topic Alias mapping by - including a non-zero length Topic Name and a Topic Alias in the PUBLISH packet. The receiver processes the - PUBLISH as normal but also sets the specified Topic Alias mapping to this Topic Name. - - If a Topic Alias mapping has been set at the receiver, a sender can send a PUBLISH packet that contains that - Topic Alias and a zero length Topic Name. The receiver then treats the incoming PUBLISH as if it had contained - the Topic Name of the Topic Alias. - - A sender can modify the Topic Alias mapping by sending another PUBLISH in the same Network Connection with the - same Topic Alias value and a different non-zero length Topic Name. - - Topic Alias mappings exist only within a Network Connection and last only for the lifetime of that Network - Connection. A receiver MUST NOT carry forward any Topic Alias mappings from one Network Connection to another - [MQTT-3.3.2-7]. - - A Topic Alias of 0 is not permitted. A sender MUST NOT send a PUBLISH packet containing a Topic Alias which - has the value 0 [MQTT-3.3.2-8]. - - A Client MUST NOT send a PUBLISH packet with a Topic Alias greater than the Topic Alias Maximum value returned - by the Server in the CONNACK packet [MQTT-3.3.2-9]. A Client MUST accept all Topic Alias values greater than 0 - and less than or equal to the Topic Alias Maximum value that it sent in the CONNECT packet [MQTT-3.3.2-10]. - - A Server MUST NOT send a PUBLISH packet with a Topic Alias greater than the Topic Alias Maximum value sent by - the Client in the CONNECT packet [MQTT-3.3.2-11]. A Server MUST accept all Topic Alias values greater than 0 - and less than or equal to the Topic Alias Maximum value that it returned in the CONNACK packet [MQTT-3.3.2-12] - - The Topic Alias mappings used by the Client and Server are independent from each other. Thus, when a Client - sends a PUBLISH containing a Topic Alias value of 1 to a Server and the Server sends a PUBLISH with a Topic - Alias value of 1 to that Client they will in general be referring to different Topics. - */ - PacketProperty.TOPIC_ALIAS, - /* - Followed by a UTF-8 Encoded String which is used as the Topic Name for a response message. The Response Topic - MUST be a UTF-8 Encoded String as defined in section 1.5.4 [MQTT-3.3.2-13]. The Response Topic MUST NOT - contain wildcard characters [MQTT-3.3.2-14]. It is a Protocol Error to include the Response Topic more than - once. The presence of a Response Topic identifies the Message as a Request. - - Refer to section 4.10 for more information about Request / Response. - - The Server MUST send the Response Topic unaltered to all subscribers receiving the Application Message - [MQTT-3.3.2-15]. - - Non-normative comment: - The receiver of an Application Message with a Response Topic sends a response by using the Response Topic as - the Topic Name of a PUBLISH. If the Request Message contains a Correlation Data, the receiver of the Request - Message should also include this Correlation Data as a property in the PUBLISH packet of the Response Message. - */ - PacketProperty.RESPONSE_TOPIC, - /* - Followed by Binary Data. The Correlation Data is used by the sender of the Request Message to identify which - request the Response Message is for when it is received. It is a Protocol Error to include Correlation Data - more than once. If the Correlation Data is not present, the Requester does not require any correlation data. - - The Server MUST send the Correlation Data unaltered to all subscribers receiving the Application Message - [MQTT-3.3.2-16]. The value of the Correlation Data only has meaning to the sender of the Request Message and - receiver of the Response Message. - - Non-normative comment - The receiver of an Application Message which contains both a Response Topic and a Correlation Data sends a - response by using the Response Topic as the Topic Name of a PUBLISH. The Client should also send the - Correlation Data unaltered as part of the PUBLISH of the responses. - - Non-normative comment - If the Correlation Data contains information which can cause application failures if modified by the Client - responding to the request, it should be encrypted and/or hashed to allow any alteration to be detected. - - Refer to section 4.10 for more information about Request / Response - */ - PacketProperty.CORRELATION_DATA, - /* - Followed by a UTF-8 String Pair. The User Property is allowed to appear multiple times to represent multiple - name, value pairs. The same name is allowed to appear more than once. - - The Server MUST send all User Properties unaltered in a PUBLISH packet when forwarding the Application Message - to a Client [MQTT-3.3.2-17]. The Server MUST maintain the order of User Properties when forwarding the - Application Message [MQTT-3.3.2-18]. - - Non-normative comment - This property is intended to provide a means of transferring application layer name-value tags whose meaning - and interpretation are known only by the application programs responsible for sending and receiving them. - */ - PacketProperty.USER_PROPERTY); - - private final String responseTopic; - private final byte[] correlationData; - private final Array userProperties; - - private final int topicAlias; - - private final boolean stringPayload; - - public Publish5OutPacket( - int packetId, - QoS qos, - boolean retained, - boolean duplicate, - String topicName, - byte[] payload, - int topicAlias, - boolean stringPayload, - String responseTopic, - byte[] correlationData, - Array userProperties) { - super(packetId, qos, retained, duplicate, topicName, payload); - this.topicAlias = topicAlias; - this.stringPayload = stringPayload; - this.responseTopic = responseTopic; - this.correlationData = correlationData; - this.userProperties = userProperties; - } - - @Override - public int expectedLength(MqttConnection connection) { - return UNKNOWN_EXPECTED_BYTES; - } - - @Override - protected boolean isPropertiesSupported(MqttConnection connection) { - return true; - } - - @Override - protected void writeProperties(MqttConnection connection, ByteBuffer buffer) { - - // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc511988586 - writeProperty(buffer, PacketProperty.PAYLOAD_FORMAT_INDICATOR, stringPayload); - writeProperty( - buffer, - PacketProperty.MESSAGE_EXPIRY_INTERVAL, - 0, - MqttProperties.MESSAGE_EXPIRY_INTERVAL_UNDEFINED); - writeProperty(buffer, PacketProperty.TOPIC_ALIAS, topicAlias, MqttProperties.TOPIC_ALIAS_DEFAULT); - writeNotEmptyProperty(buffer, PacketProperty.RESPONSE_TOPIC, responseTopic); - writeNotEmptyProperty(buffer, PacketProperty.CORRELATION_DATA, correlationData); - writeStringPairProperties(buffer, PacketProperty.USER_PROPERTY, userProperties); - } -} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/PublishComplete311OutPacket.java b/network/src/main/java/javasabr/mqtt/network/packet/out/PublishComplete311OutPacket.java deleted file mode 100644 index ed0d9a41..00000000 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/PublishComplete311OutPacket.java +++ /dev/null @@ -1,33 +0,0 @@ -package javasabr.mqtt.network.packet.out; - -import java.nio.ByteBuffer; -import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.MqttPacketType; -import lombok.RequiredArgsConstructor; - -/** - * Publish complete (QoS 2 delivery part 3). - */ -@RequiredArgsConstructor -public class PublishComplete311OutPacket extends MqttWritablePacket { - - private static final byte PACKET_TYPE = (byte) MqttPacketType.PUBLISH_COMPLETED.ordinal(); - - private final int packetId; - - @Override - public int expectedLength(MqttConnection connection) { - return 2; - } - - @Override - protected byte packetType() { - return PACKET_TYPE; - } - - @Override - protected void writeVariableHeader(MqttConnection connection, ByteBuffer buffer) { - // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718083 - writeShort(buffer, packetId); - } -} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/PublishOutPacket.java b/network/src/main/java/javasabr/mqtt/network/packet/out/PublishOutPacket.java deleted file mode 100644 index dbafc2e8..00000000 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/PublishOutPacket.java +++ /dev/null @@ -1,22 +0,0 @@ -package javasabr.mqtt.network.packet.out; - -import javasabr.mqtt.network.packet.HasPacketId; -import javasabr.mqtt.network.packet.MqttPacketType; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import lombok.experimental.Accessors; - -@Accessors(fluent = true) -@RequiredArgsConstructor -public abstract class PublishOutPacket extends MqttWritablePacket implements HasPacketId { - - private static final byte PACKET_TYPE = (byte) MqttPacketType.PUBLISH.ordinal(); - - @Getter - protected final int packetId; - - @Override - protected byte packetType() { - return PACKET_TYPE; - } -} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/PublishReceived311OutPacket.java b/network/src/main/java/javasabr/mqtt/network/packet/out/PublishReceived311OutPacket.java deleted file mode 100644 index f150e965..00000000 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/PublishReceived311OutPacket.java +++ /dev/null @@ -1,33 +0,0 @@ -package javasabr.mqtt.network.packet.out; - -import java.nio.ByteBuffer; -import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.MqttPacketType; -import lombok.RequiredArgsConstructor; - -/** - * Publish received (QoS 2 delivery part 1). - */ -@RequiredArgsConstructor -public class PublishReceived311OutPacket extends MqttWritablePacket { - - private static final byte PACKET_TYPE = (byte) MqttPacketType.PUBLISH_RECEIVED.ordinal(); - - private final int packetId; - - @Override - public int expectedLength(MqttConnection connection) { - return 2; - } - - @Override - protected byte packetType() { - return PACKET_TYPE; - } - - @Override - protected void writeVariableHeader(MqttConnection connection, ByteBuffer buffer) { - // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718050 - writeShort(buffer, packetId); - } -} diff --git a/network/src/main/java/javasabr/mqtt/network/packet/out/Subscribe311OutPacket.java b/network/src/main/java/javasabr/mqtt/network/packet/out/Subscribe311OutPacket.java deleted file mode 100644 index 588a856e..00000000 --- a/network/src/main/java/javasabr/mqtt/network/packet/out/Subscribe311OutPacket.java +++ /dev/null @@ -1,49 +0,0 @@ -package javasabr.mqtt.network.packet.out; - -import java.nio.ByteBuffer; -import javasabr.mqtt.model.subscriber.SubscribeTopicFilter; -import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.MqttPacketType; -import javasabr.rlib.collections.array.Array; -import lombok.RequiredArgsConstructor; - -/** - * Subscribe request. - */ -@RequiredArgsConstructor -public class Subscribe311OutPacket extends MqttWritablePacket { - - private static final byte PACKET_TYPE = (byte) MqttPacketType.SUBSCRIBE.ordinal(); - - private final Array topicFilters; - private final int packetId; - - @Override - protected byte packetType() { - return PACKET_TYPE; - } - - @Override - protected void writeVariableHeader(MqttConnection connection, ByteBuffer buffer) { - // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718065 - writeShort(buffer, packetId); - } - - @Override - protected void writePayload(MqttConnection connection, ByteBuffer buffer) { - // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718066 - for (var topicFilter : topicFilters) { - writeString(buffer, - topicFilter - .getTopicFilter() - .toString()); - writeByte(buffer, buildSubscriptionOptions(topicFilter)); - } - } - - protected int buildSubscriptionOptions(SubscribeTopicFilter topicFilter) { - return topicFilter - .getQos() - .ordinal(); - } -} diff --git a/network/src/main/java/javasabr/mqtt/network/utils/MqttDataUtils.java b/network/src/main/java/javasabr/mqtt/network/util/MqttDataUtils.java similarity index 98% rename from network/src/main/java/javasabr/mqtt/network/utils/MqttDataUtils.java rename to network/src/main/java/javasabr/mqtt/network/util/MqttDataUtils.java index fd2e18c8..cb425c62 100644 --- a/network/src/main/java/javasabr/mqtt/network/utils/MqttDataUtils.java +++ b/network/src/main/java/javasabr/mqtt/network/util/MqttDataUtils.java @@ -1,4 +1,4 @@ -package javasabr.mqtt.network.utils; +package javasabr.mqtt.network.util; import java.nio.ByteBuffer; diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/in/AuthenticationInPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/in/AuthenticationMqttInMessageTest.groovy similarity index 88% rename from application/src/test/groovy/javasabr/mqtt/application/network/in/AuthenticationInPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/in/AuthenticationMqttInMessageTest.groovy index 7643205a..31453d38 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/in/AuthenticationInPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/in/AuthenticationMqttInMessageTest.groovy @@ -1,12 +1,11 @@ -package javasabr.mqtt.application.network.in +package javasabr.mqtt.network.message.in import javasabr.mqtt.model.PacketProperty import javasabr.mqtt.model.reason.code.AuthenticateReasonCode -import javasabr.mqtt.network.packet.in.AuthenticationInPacket import javasabr.rlib.collections.array.Array import javasabr.rlib.common.util.BufferUtils -class AuthenticationInPacketTest extends BaseInPacketTest { +class AuthenticationMqttInMessageTest extends BaseMqttInMessageTest { def "should read packet correctly as mqtt 5.0"() { given: @@ -22,7 +21,7 @@ class AuthenticationInPacketTest extends BaseInPacketTest { it.put(propertiesBuffer) } when: - def packet = new AuthenticationInPacket(0b1111_0000 as byte) + def packet = new AuthenticationMqttInMessage(0b1111_0000 as byte) def result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result @@ -43,7 +42,7 @@ class AuthenticationInPacketTest extends BaseInPacketTest { it.putMbi(propertiesBuffer.limit()) it.put(propertiesBuffer) } - packet = new AuthenticationInPacket(0b1111_0000 as byte) + packet = new AuthenticationMqttInMessage(0b1111_0000 as byte) result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result @@ -62,7 +61,7 @@ class AuthenticationInPacketTest extends BaseInPacketTest { it.putMbi(propertiesBuffer.limit()) it.put(propertiesBuffer) } - packet = new AuthenticationInPacket(0b1111_0000 as byte) + packet = new AuthenticationMqttInMessage(0b1111_0000 as byte) result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result diff --git a/network/src/test/groovy/javasabr/mqtt/network/message/in/BaseMqttInMessageTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/in/BaseMqttInMessageTest.groovy new file mode 100644 index 00000000..f2a674e1 --- /dev/null +++ b/network/src/test/groovy/javasabr/mqtt/network/message/in/BaseMqttInMessageTest.groovy @@ -0,0 +1,6 @@ +package javasabr.mqtt.network.message.in + +import javasabr.mqtt.network.NetworkUnitSpecification + +class BaseMqttInMessageTest extends NetworkUnitSpecification { +} diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/in/ConnectAckInPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/in/ConnectAckMqttInMessageTest.groovy similarity index 94% rename from application/src/test/groovy/javasabr/mqtt/application/network/in/ConnectAckInPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/in/ConnectAckMqttInMessageTest.groovy index b3e11388..c801720d 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/in/ConnectAckInPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/in/ConnectAckMqttInMessageTest.groovy @@ -1,14 +1,13 @@ -package javasabr.mqtt.application.network.in +package javasabr.mqtt.network.message.in import javasabr.mqtt.model.MqttProperties import javasabr.mqtt.model.PacketProperty import javasabr.mqtt.model.QoS import javasabr.mqtt.model.reason.code.ConnectAckReasonCode -import javasabr.mqtt.network.packet.in.ConnectAckInPacket import javasabr.rlib.common.util.ArrayUtils import javasabr.rlib.common.util.BufferUtils -class ConnectAckInPacketTest extends BaseInPacketTest { +class ConnectAckMqttInMessageTest extends BaseMqttInMessageTest { def "should read packet correctly as mqtt 3.1.1"() { given: @@ -17,7 +16,7 @@ class ConnectAckInPacketTest extends BaseInPacketTest { it.put(ConnectAckReasonCode.NOT_AUTHORIZED.mqtt311) } when: - def packet = new ConnectAckInPacket(0b0010_0000 as byte) + def packet = new ConnectAckMqttInMessage(0b0010_0000 as byte) def result = packet.read(defaultMqtt311Connection, dataBuffer, dataBuffer.limit()) then: result @@ -68,7 +67,7 @@ class ConnectAckInPacketTest extends BaseInPacketTest { it.put(propertiesBuffer) } when: - def packet = new ConnectAckInPacket(0b0010_0000 as byte) + def packet = new ConnectAckMqttInMessage(0b0010_0000 as byte) def result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result @@ -103,7 +102,7 @@ class ConnectAckInPacketTest extends BaseInPacketTest { it.putMbi(propertiesBuffer.limit()) it.put(propertiesBuffer) } - packet = new ConnectAckInPacket(0b0010_0000 as byte) + packet = new ConnectAckMqttInMessage(0b0010_0000 as byte) result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/in/ConnectInPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/in/ConnectMqttInMessageTest.groovy similarity index 92% rename from application/src/test/groovy/javasabr/mqtt/application/network/in/ConnectInPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/in/ConnectMqttInMessageTest.groovy index 80a5c1b3..1a74f132 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/in/ConnectInPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/in/ConnectMqttInMessageTest.groovy @@ -1,13 +1,12 @@ -package javasabr.mqtt.application.network.in +package javasabr.mqtt.network.message.in import javasabr.mqtt.model.MqttVersion import javasabr.mqtt.model.PacketProperty import javasabr.mqtt.model.exception.MalformedPacketMqttException -import javasabr.mqtt.network.packet.in.ConnectInPacket import javasabr.rlib.common.util.ArrayUtils import javasabr.rlib.common.util.BufferUtils -class ConnectInPacketTest extends BaseInPacketTest { +class ConnectMqttInMessageTest extends BaseMqttInMessageTest { def "should read packet correctly as mqtt 3.1.1"() { given: @@ -21,7 +20,7 @@ class ConnectInPacketTest extends BaseInPacketTest { it.putBytes(userPassword) } when: - def packet = new ConnectInPacket(0b0001_0000 as byte) + def packet = new ConnectMqttInMessage(0b0001_0000 as byte) def result = packet.read(defaultMqtt311Connection, dataBuffer, dataBuffer.limit()) then: result @@ -59,7 +58,7 @@ class ConnectInPacketTest extends BaseInPacketTest { it.putBytes(userPassword) } when: - def packet = new ConnectInPacket(0b0001_0000 as byte) + def packet = new ConnectMqttInMessage(0b0001_0000 as byte) def result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result @@ -93,7 +92,7 @@ class ConnectInPacketTest extends BaseInPacketTest { it.putBytes(userPassword) } when: - def packet = new ConnectInPacket(0b0001_0000 as byte) + def packet = new ConnectMqttInMessage(0b0001_0000 as byte) def result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: !result diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/in/DisconnectInPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/in/DisconnectMqttInMessageTest.groovy similarity index 87% rename from application/src/test/groovy/javasabr/mqtt/application/network/in/DisconnectInPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/in/DisconnectMqttInMessageTest.groovy index 89fde74d..1d7492eb 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/in/DisconnectInPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/in/DisconnectMqttInMessageTest.groovy @@ -1,12 +1,11 @@ -package javasabr.mqtt.application.network.in +package javasabr.mqtt.network.message.in import javasabr.mqtt.model.PacketProperty import javasabr.mqtt.model.reason.code.DisconnectReasonCode -import javasabr.mqtt.network.packet.in.DisconnectInPacket import javasabr.rlib.collections.array.Array import javasabr.rlib.common.util.BufferUtils -class DisconnectInPacketTest extends BaseInPacketTest { +class DisconnectMqttInMessageTest extends BaseMqttInMessageTest { def "should read packet correctly as mqtt 5.0"() { given: @@ -22,7 +21,7 @@ class DisconnectInPacketTest extends BaseInPacketTest { it.put(propertiesBuffer) } when: - def packet = new DisconnectInPacket(0b1110_0000 as byte) + def packet = new DisconnectMqttInMessage(0b1110_0000 as byte) def result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result @@ -41,7 +40,7 @@ class DisconnectInPacketTest extends BaseInPacketTest { it.putMbi(propertiesBuffer.limit()) it.put(propertiesBuffer) } - packet = new DisconnectInPacket(0b1110_0000 as byte) + packet = new DisconnectMqttInMessage(0b1110_0000 as byte) result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/in/PublishAckInPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/in/PublishAckMqttInMessageTest.groovy similarity index 80% rename from application/src/test/groovy/javasabr/mqtt/application/network/in/PublishAckInPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/in/PublishAckMqttInMessageTest.groovy index cd95702a..00d44f33 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/in/PublishAckInPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/in/PublishAckMqttInMessageTest.groovy @@ -1,12 +1,11 @@ -package javasabr.mqtt.application.network.in +package javasabr.mqtt.network.message.in import javasabr.mqtt.model.PacketProperty import javasabr.mqtt.model.reason.code.PublishAckReasonCode -import javasabr.mqtt.network.packet.in.PublishAckInPacket import javasabr.rlib.collections.array.Array import javasabr.rlib.common.util.BufferUtils -class PublishAckInPacketTest extends BaseInPacketTest { +class PublishAckMqttInMessageTest extends BaseMqttInMessageTest { def "should read packet correctly as mqtt 3.1.1"() { given: @@ -14,12 +13,12 @@ class PublishAckInPacketTest extends BaseInPacketTest { it.putShort(packetId) } when: - def packet = new PublishAckInPacket(0b0100_0000 as byte) + def packet = new PublishAckMqttInMessage(0b0100_0000 as byte) def result = packet.read(defaultMqtt311Connection, dataBuffer, dataBuffer.limit()) then: result packet.reason() == "" - packet.packetId() == packetId + packet.messageId() == packetId packet.reasonCode() == PublishAckReasonCode.SUCCESS packet.userProperties() == Array.empty() } @@ -37,12 +36,12 @@ class PublishAckInPacketTest extends BaseInPacketTest { it.put(propertiesBuffer) } when: - def packet = new PublishAckInPacket(0b0100_0000 as byte) + def packet = new PublishAckMqttInMessage(0b0100_0000 as byte) def result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result packet.reason() == reasonString - packet.packetId() == packetId + packet.messageId() == packetId packet.reasonCode() == PublishAckReasonCode.PAYLOAD_FORMAT_INVALID packet.userProperties() == userProperties when: @@ -51,12 +50,12 @@ class PublishAckInPacketTest extends BaseInPacketTest { it.put(PublishAckReasonCode.UNSPECIFIED_ERROR.value) it.putMbi(0) } - packet = new PublishAckInPacket(0b0100_0000 as byte) + packet = new PublishAckMqttInMessage(0b0100_0000 as byte) result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result packet.reason() == "" - packet.packetId() == packetId + packet.messageId() == packetId packet.reasonCode() == PublishAckReasonCode.UNSPECIFIED_ERROR packet.userProperties() == Array.empty() } diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/in/PublishCompleteInPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/in/PublishCompleteMqttInMessageTest.groovy similarity index 80% rename from application/src/test/groovy/javasabr/mqtt/application/network/in/PublishCompleteInPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/in/PublishCompleteMqttInMessageTest.groovy index f050618f..7b5cda40 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/in/PublishCompleteInPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/in/PublishCompleteMqttInMessageTest.groovy @@ -1,12 +1,11 @@ -package javasabr.mqtt.application.network.in +package javasabr.mqtt.network.message.in import javasabr.mqtt.model.PacketProperty import javasabr.mqtt.model.reason.code.PublishCompletedReasonCode -import javasabr.mqtt.network.packet.in.PublishCompleteInPacket import javasabr.rlib.collections.array.Array import javasabr.rlib.common.util.BufferUtils -class PublishCompleteInPacketTest extends BaseInPacketTest { +class PublishCompleteMqttInMessageTest extends BaseMqttInMessageTest { def "should read packet correctly as mqtt 3.1.1"() { given: @@ -14,12 +13,12 @@ class PublishCompleteInPacketTest extends BaseInPacketTest { it.putShort(packetId) } when: - def packet = new PublishCompleteInPacket(0b0111_0000 as byte) + def packet = new PublishCompleteMqttInMessage(0b0111_0000 as byte) def result = packet.read(defaultMqtt311Connection, dataBuffer, dataBuffer.limit()) then: result packet.reason() == "" - packet.packetId() == packetId + packet.messageId() == packetId packet.reasonCode() == PublishCompletedReasonCode.SUCCESS packet.userProperties() == Array.empty() } @@ -37,12 +36,12 @@ class PublishCompleteInPacketTest extends BaseInPacketTest { it.put(propertiesBuffer) } when: - def packet = new PublishCompleteInPacket(0b0111_0000 as byte) + def packet = new PublishCompleteMqttInMessage(0b0111_0000 as byte) def result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result packet.reason() == reasonString - packet.packetId() == packetId + packet.messageId() == packetId packet.reasonCode() == PublishCompletedReasonCode.PACKET_IDENTIFIER_NOT_FOUND packet.userProperties() == userProperties when: @@ -51,12 +50,12 @@ class PublishCompleteInPacketTest extends BaseInPacketTest { it.put(PublishCompletedReasonCode.PACKET_IDENTIFIER_NOT_FOUND.value) it.putMbi(0) } - packet = new PublishCompleteInPacket(0b0111_0000 as byte) + packet = new PublishCompleteMqttInMessage(0b0111_0000 as byte) result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result packet.reason() == "" - packet.packetId() == packetId + packet.messageId() == packetId packet.reasonCode() == PublishCompletedReasonCode.PACKET_IDENTIFIER_NOT_FOUND packet.userProperties() == Array.empty() } diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/in/PublishInPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/in/PublishMqttInMessageTest.groovy similarity index 89% rename from application/src/test/groovy/javasabr/mqtt/application/network/in/PublishInPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/in/PublishMqttInMessageTest.groovy index d861b808..3b658bce 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/in/PublishInPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/in/PublishMqttInMessageTest.groovy @@ -1,16 +1,15 @@ -package javasabr.mqtt.application.network.in +package javasabr.mqtt.network.message.in import javasabr.mqtt.model.MqttProperties import javasabr.mqtt.model.PacketProperty import javasabr.mqtt.model.QoS import javasabr.mqtt.model.data.type.StringPair -import javasabr.mqtt.network.packet.in.PublishInPacket import javasabr.rlib.collections.array.Array import javasabr.rlib.collections.array.IntArray import javasabr.rlib.common.util.ArrayUtils import javasabr.rlib.common.util.BufferUtils -class PublishInPacketTest extends BaseInPacketTest { +class PublishMqttInMessageTest extends BaseMqttInMessageTest { def "should read packet correctly as mqtt 3.1.1"() { given: @@ -20,7 +19,7 @@ class PublishInPacketTest extends BaseInPacketTest { it.put(publishPayload) } when: - def packet = new PublishInPacket(0b0110_0011 as byte) + def packet = new PublishMqttInMessage(0b0110_0011 as byte) def result = packet.read(defaultMqtt311Connection, dataBuffer, dataBuffer.limit()) then: result @@ -32,7 +31,7 @@ class PublishInPacketTest extends BaseInPacketTest { packet.contentType == "" packet.correlationData == ArrayUtils.EMPTY_BYTE_ARRAY packet.payload == publishPayload - packet.packetId == packetId + packet.messageId == packetId packet.userProperties() == Array.empty() packet.messageExpiryInterval == MqttProperties.MESSAGE_EXPIRY_INTERVAL_UNDEFINED packet.topicAlias == MqttProperties.TOPIC_ALIAS_DEFAULT @@ -59,7 +58,7 @@ class PublishInPacketTest extends BaseInPacketTest { it.put(publishPayload) } when: - def packet = new PublishInPacket(0b0110_0011 as byte) + def packet = new PublishMqttInMessage(0b0110_0011 as byte) def result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result @@ -71,7 +70,7 @@ class PublishInPacketTest extends BaseInPacketTest { packet.contentType == contentType packet.correlationData == correlationData packet.payload == publishPayload - packet.packetId == packetId + packet.messageId == packetId packet.userProperties() == userProperties packet.messageExpiryInterval == messageExpiryInterval packet.topicAlias == topicAlias @@ -83,7 +82,7 @@ class PublishInPacketTest extends BaseInPacketTest { it.putMbi(0) it.put(publishPayload) } - packet = new PublishInPacket(0b0110_0011 as byte) + packet = new PublishMqttInMessage(0b0110_0011 as byte) result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result @@ -95,7 +94,7 @@ class PublishInPacketTest extends BaseInPacketTest { packet.contentType == "" packet.correlationData == ArrayUtils.EMPTY_BYTE_ARRAY packet.payload == publishPayload - packet.packetId == packetId + packet.messageId == packetId packet.userProperties() == Array.empty(StringPair) packet.messageExpiryInterval == MqttProperties.MESSAGE_EXPIRY_INTERVAL_UNDEFINED packet.topicAlias == MqttProperties.TOPIC_ALIAS_DEFAULT diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/in/PublishReceivedInPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/in/PublishReceivedMqttInMessageTest.groovy similarity index 79% rename from application/src/test/groovy/javasabr/mqtt/application/network/in/PublishReceivedInPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/in/PublishReceivedMqttInMessageTest.groovy index 8bef9d39..a4f498e0 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/in/PublishReceivedInPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/in/PublishReceivedMqttInMessageTest.groovy @@ -1,12 +1,11 @@ -package javasabr.mqtt.application.network.in +package javasabr.mqtt.network.message.in import javasabr.mqtt.model.PacketProperty import javasabr.mqtt.model.reason.code.PublishReceivedReasonCode -import javasabr.mqtt.network.packet.in.PublishReceivedInPacket import javasabr.rlib.collections.array.Array import javasabr.rlib.common.util.BufferUtils -class PublishReceivedInPacketTest extends BaseInPacketTest { +class PublishReceivedMqttInMessageTest extends BaseMqttInMessageTest { def "should read packet correctly as mqtt 3.1.1"() { given: @@ -14,12 +13,12 @@ class PublishReceivedInPacketTest extends BaseInPacketTest { it.putShort(packetId) } when: - def packet = new PublishReceivedInPacket(0b0101_0000 as byte) + def packet = new PublishReceivedMqttInMessage(0b0101_0000 as byte) def result = packet.read(defaultMqtt311Connection, dataBuffer, dataBuffer.limit()) then: result packet.reason() == "" - packet.packetId() == packetId + packet.messageId() == packetId packet.reasonCode() == PublishReceivedReasonCode.SUCCESS packet.userProperties() == Array.empty() } @@ -37,12 +36,12 @@ class PublishReceivedInPacketTest extends BaseInPacketTest { it.put(propertiesBuffer) } when: - def packet = new PublishReceivedInPacket(0b0101_0000 as byte) + def packet = new PublishReceivedMqttInMessage(0b0101_0000 as byte) def result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result packet.reason() == reasonString - packet.packetId() == packetId + packet.messageId() == packetId packet.reasonCode() == PublishReceivedReasonCode.QUOTA_EXCEEDED packet.userProperties() == userProperties when: @@ -51,12 +50,12 @@ class PublishReceivedInPacketTest extends BaseInPacketTest { it.put(PublishReceivedReasonCode.IMPLEMENTATION_SPECIFIC_ERROR.value) it.putMbi(0) } - packet = new PublishReceivedInPacket(0b0101_0000 as byte) + packet = new PublishReceivedMqttInMessage(0b0101_0000 as byte) result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result packet.reason() == "" - packet.packetId() == packetId + packet.messageId() == packetId packet.reasonCode() == PublishReceivedReasonCode.IMPLEMENTATION_SPECIFIC_ERROR packet.userProperties() == Array.empty() } diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/in/PublishReleaseInPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/in/PublishReleaseMqttInMessageTest.groovy similarity index 79% rename from application/src/test/groovy/javasabr/mqtt/application/network/in/PublishReleaseInPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/in/PublishReleaseMqttInMessageTest.groovy index 33391925..d455b256 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/in/PublishReleaseInPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/in/PublishReleaseMqttInMessageTest.groovy @@ -1,12 +1,11 @@ -package javasabr.mqtt.application.network.in +package javasabr.mqtt.network.message.in import javasabr.mqtt.model.PacketProperty import javasabr.mqtt.model.reason.code.PublishReleaseReasonCode -import javasabr.mqtt.network.packet.in.PublishReleaseInPacket import javasabr.rlib.collections.array.Array import javasabr.rlib.common.util.BufferUtils -class PublishReleaseInPacketTest extends BaseInPacketTest { +class PublishReleaseMqttInMessageTest extends BaseMqttInMessageTest { def "should read packet correctly as mqtt 3.1.1"() { given: @@ -14,12 +13,12 @@ class PublishReleaseInPacketTest extends BaseInPacketTest { it.putShort(packetId) } when: - def packet = new PublishReleaseInPacket(0b0110_0000 as byte) + def packet = new PublishReleaseMqttInMessage(0b0110_0000 as byte) def result = packet.read(defaultMqtt311Connection, dataBuffer, dataBuffer.limit()) then: result packet.reason() == "" - packet.packetId() == packetId + packet.messageId() == packetId packet.reasonCode() == PublishReleaseReasonCode.SUCCESS packet.userProperties() == Array.empty() } @@ -37,12 +36,12 @@ class PublishReleaseInPacketTest extends BaseInPacketTest { it.put(propertiesBuffer) } when: - def packet = new PublishReleaseInPacket(0b0110_0000 as byte) + def packet = new PublishReleaseMqttInMessage(0b0110_0000 as byte) def result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result packet.reason() == reasonString - packet.packetId() == packetId + packet.messageId() == packetId packet.reasonCode() == PublishReleaseReasonCode.PACKET_IDENTIFIER_NOT_FOUND packet.userProperties() == userProperties when: @@ -51,12 +50,12 @@ class PublishReleaseInPacketTest extends BaseInPacketTest { it.put(PublishReleaseReasonCode.SUCCESS.value) it.putMbi(0) } - packet = new PublishReleaseInPacket(0b0110_0000 as byte) + packet = new PublishReleaseMqttInMessage(0b0110_0000 as byte) result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result packet.reason() == "" - packet.packetId() == packetId + packet.messageId() == packetId packet.reasonCode() == PublishReleaseReasonCode.SUCCESS packet.userProperties() == Array.empty() } diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/in/SubscribeAckInPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/in/SubscribeAckMqttInMessageTest.groovy similarity index 87% rename from application/src/test/groovy/javasabr/mqtt/application/network/in/SubscribeAckInPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/in/SubscribeAckMqttInMessageTest.groovy index fa49b4bd..1f1cdc50 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/in/SubscribeAckInPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/in/SubscribeAckMqttInMessageTest.groovy @@ -1,12 +1,11 @@ -package javasabr.mqtt.application.network.in +package javasabr.mqtt.network.message.in import javasabr.mqtt.model.PacketProperty import javasabr.mqtt.model.reason.code.SubscribeAckReasonCode -import javasabr.mqtt.network.packet.in.SubscribeAckInPacket import javasabr.rlib.collections.array.Array import javasabr.rlib.common.util.BufferUtils -class SubscribeAckInPacketTest extends BaseInPacketTest { +class SubscribeAckMqttInMessageTest extends BaseMqttInMessageTest { def "should read packet correctly as mqtt 3.1.1"() { given: @@ -18,12 +17,12 @@ class SubscribeAckInPacketTest extends BaseInPacketTest { it.put(SubscribeAckReasonCode.UNSPECIFIED_ERROR.value) } when: - def packet = new SubscribeAckInPacket(0b1001_0000 as byte) + def packet = new SubscribeAckMqttInMessage(0b1001_0000 as byte) def result = packet.read(defaultMqtt311Connection, dataBuffer, dataBuffer.limit()) then: result packet.reason == "" - packet.packetId == packetId + packet.messageId == packetId packet.reasonCodes.size() == 4 packet.reasonCodes.get(0) == SubscribeAckReasonCode.GRANTED_QOS_0 packet.reasonCodes.get(1) == SubscribeAckReasonCode.GRANTED_QOS_2 @@ -47,12 +46,12 @@ class SubscribeAckInPacketTest extends BaseInPacketTest { it.put(SubscribeAckReasonCode.UNSPECIFIED_ERROR.value) } when: - def packet = new SubscribeAckInPacket(0b1001_0000 as byte) + def packet = new SubscribeAckMqttInMessage(0b1001_0000 as byte) def result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result packet.reason == reasonString - packet.packetId == packetId + packet.messageId == packetId packet.reasonCodes.size() == 4 packet.reasonCodes.get(0) == SubscribeAckReasonCode.GRANTED_QOS_0 packet.reasonCodes.get(1) == SubscribeAckReasonCode.IMPLEMENTATION_SPECIFIC_ERROR @@ -68,12 +67,12 @@ class SubscribeAckInPacketTest extends BaseInPacketTest { it.put(SubscribeAckReasonCode.GRANTED_QOS_1.value) it.put(SubscribeAckReasonCode.UNSPECIFIED_ERROR.value) } - packet = new SubscribeAckInPacket(0b1001_0000 as byte) + packet = new SubscribeAckMqttInMessage(0b1001_0000 as byte) result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result packet.reason == "" - packet.packetId == packetId + packet.messageId == packetId packet.reasonCodes.size() == 4 packet.reasonCodes.get(0) == SubscribeAckReasonCode.SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED packet.reasonCodes.get(1) == SubscribeAckReasonCode.GRANTED_QOS_2 diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/in/SubscribeInPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/in/SubscribeMqttInMessageTest.groovy similarity index 90% rename from application/src/test/groovy/javasabr/mqtt/application/network/in/SubscribeInPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/in/SubscribeMqttInMessageTest.groovy index 7e2898b7..ca9e546b 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/in/SubscribeInPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/in/SubscribeMqttInMessageTest.groovy @@ -1,14 +1,13 @@ -package javasabr.mqtt.application.network.in +package javasabr.mqtt.network.message.in import javasabr.mqtt.model.MqttProperties import javasabr.mqtt.model.PacketProperty import javasabr.mqtt.model.QoS import javasabr.mqtt.model.SubscribeRetainHandling -import javasabr.mqtt.network.packet.in.SubscribeInPacket import javasabr.rlib.collections.array.Array import javasabr.rlib.common.util.BufferUtils -class SubscribeInPacketTest extends BaseInPacketTest { +class SubscribeMqttInMessageTest extends BaseMqttInMessageTest { def "should read packet correctly as mqtt 3.1.1"() { given: @@ -20,7 +19,7 @@ class SubscribeInPacketTest extends BaseInPacketTest { it.put(0b0000_0010 as byte) } when: - def packet = new SubscribeInPacket(0b1000_0000 as byte) + def packet = new SubscribeMqttInMessage(0b1000_0000 as byte) def result = packet.read(defaultMqtt311Connection, dataBuffer, dataBuffer.limit()) then: result @@ -35,7 +34,7 @@ class SubscribeInPacketTest extends BaseInPacketTest { packet.topicFilters.get(1).isNoLocal() packet.topicFilters.get(1).isRetainAsPublished() packet.topicFilters.get(1).getRetainHandling() == SubscribeRetainHandling.SEND - packet.packetId == packetId + packet.messageId == packetId packet.userProperties() == Array.empty() packet.subscriptionId == MqttProperties.SUBSCRIPTION_ID_UNDEFINED } @@ -56,7 +55,7 @@ class SubscribeInPacketTest extends BaseInPacketTest { it.put(0b0001_0110 as byte) } when: - def packet = new SubscribeInPacket(0b0110_0000 as byte) + def packet = new SubscribeMqttInMessage(0b0110_0000 as byte) def result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result @@ -71,7 +70,7 @@ class SubscribeInPacketTest extends BaseInPacketTest { packet.topicFilters.get(1).isNoLocal() !packet.topicFilters.get(1).isRetainAsPublished() packet.topicFilters.get(1).getRetainHandling() == SubscribeRetainHandling.SEND_IF_SUBSCRIPTION_DOES_NOT_EXIST - packet.packetId == packetId + packet.messageId == packetId packet.userProperties() == userProperties packet.subscriptionId == subscriptionId when: @@ -83,7 +82,7 @@ class SubscribeInPacketTest extends BaseInPacketTest { it.putString(topicFilter2) it.put(0b0000_0010 as byte) } - packet = new SubscribeInPacket(0b0110_0000 as byte) + packet = new SubscribeMqttInMessage(0b0110_0000 as byte) result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result @@ -98,7 +97,7 @@ class SubscribeInPacketTest extends BaseInPacketTest { !packet.topicFilters.get(1).isNoLocal() !packet.topicFilters.get(1).isRetainAsPublished() packet.topicFilters.get(1).getRetainHandling() == SubscribeRetainHandling.SEND - packet.packetId == packetId + packet.messageId == packetId packet.userProperties() == Array.empty() packet.subscriptionId == MqttProperties.SUBSCRIPTION_ID_UNDEFINED } diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/in/UnsubscribeAckInPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/in/UnsubscribeAckMqttInMessageTest.groovy similarity index 83% rename from application/src/test/groovy/javasabr/mqtt/application/network/in/UnsubscribeAckInPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/in/UnsubscribeAckMqttInMessageTest.groovy index 7e9c8f02..bafce0b9 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/in/UnsubscribeAckInPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/in/UnsubscribeAckMqttInMessageTest.groovy @@ -1,12 +1,11 @@ -package javasabr.mqtt.application.network.in +package javasabr.mqtt.network.message.in import javasabr.mqtt.model.PacketProperty import javasabr.mqtt.model.reason.code.UnsubscribeAckReasonCode -import javasabr.mqtt.network.packet.in.UnsubscribeAckInPacket import javasabr.rlib.collections.array.Array import javasabr.rlib.common.util.BufferUtils -class UnsubscribeAckInPacketTest extends BaseInPacketTest { +class UnsubscribeAckMqttInMessageTest extends BaseMqttInMessageTest { def "should read packet correctly as mqtt 3.1.1"() { given: @@ -14,12 +13,12 @@ class UnsubscribeAckInPacketTest extends BaseInPacketTest { it.putShort(packetId) } when: - def packet = new UnsubscribeAckInPacket(0b1011_0000 as byte) + def packet = new UnsubscribeAckMqttInMessage(0b1011_0000 as byte) def result = packet.read(defaultMqtt311Connection, dataBuffer, dataBuffer.limit()) then: result packet.reason() == "" - packet.packetId() == packetId + packet.messageId() == packetId packet.reasonCodes() == Array.empty() } @@ -39,12 +38,12 @@ class UnsubscribeAckInPacketTest extends BaseInPacketTest { it.put(UnsubscribeAckReasonCode.UNSPECIFIED_ERROR.value) } when: - def packet = new UnsubscribeAckInPacket(0b1011_0000 as byte) + def packet = new UnsubscribeAckMqttInMessage(0b1011_0000 as byte) def result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result packet.reason() == reasonString - packet.packetId() == packetId + packet.messageId() == packetId packet.reasonCodes().size() == 4 packet.reasonCodes().get(0) == UnsubscribeAckReasonCode.SUCCESS packet.reasonCodes().get(1) == UnsubscribeAckReasonCode.SUCCESS @@ -58,12 +57,12 @@ class UnsubscribeAckInPacketTest extends BaseInPacketTest { it.put(UnsubscribeAckReasonCode.UNSPECIFIED_ERROR.value) it.put(UnsubscribeAckReasonCode.IMPLEMENTATION_SPECIFIC_ERROR.value) } - packet = new UnsubscribeAckInPacket(0b1011_0000 as byte) + packet = new UnsubscribeAckMqttInMessage(0b1011_0000 as byte) result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result packet.reason() == "" - packet.packetId() == packetId + packet.messageId() == packetId packet.reasonCodes().size() == 2 packet.reasonCodes().get(0) == UnsubscribeAckReasonCode.UNSPECIFIED_ERROR packet.reasonCodes().get(1) == UnsubscribeAckReasonCode.IMPLEMENTATION_SPECIFIC_ERROR diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/in/UnsubscribeInPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/in/UnsubscribeMqttInMessageTest.groovy similarity index 81% rename from application/src/test/groovy/javasabr/mqtt/application/network/in/UnsubscribeInPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/in/UnsubscribeMqttInMessageTest.groovy index dd7d14e6..c4bdc9d3 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/in/UnsubscribeInPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/in/UnsubscribeMqttInMessageTest.groovy @@ -1,11 +1,10 @@ -package javasabr.mqtt.application.network.in +package javasabr.mqtt.network.message.in import javasabr.mqtt.model.PacketProperty -import javasabr.mqtt.network.packet.in.UnsubscribeInPacket import javasabr.rlib.collections.array.Array import javasabr.rlib.common.util.BufferUtils -class UnsubscribeInPacketTest extends BaseInPacketTest { +class UnsubscribeMqttInMessageTest extends BaseMqttInMessageTest { def "should read packet correctly as mqtt 3.1.1"() { given: @@ -15,14 +14,14 @@ class UnsubscribeInPacketTest extends BaseInPacketTest { it.putString(topicFilter2) } when: - def packet = new UnsubscribeInPacket(0b1011_0000 as byte) + def packet = new UnsubscribeMqttInMessage(0b1011_0000 as byte) def result = packet.read(defaultMqtt311Connection, dataBuffer, dataBuffer.limit()) then: result packet.topicFilters.size() == 2 packet.topicFilters.get(0).toString() == topicFilter packet.topicFilters.get(1).toString() == topicFilter2 - packet.packetId == packetId + packet.messageId == packetId packet.userProperties() == Array.empty() } @@ -39,14 +38,14 @@ class UnsubscribeInPacketTest extends BaseInPacketTest { it.putString(topicFilter2) } when: - def packet = new UnsubscribeInPacket(0b1011_0000 as byte) + def packet = new UnsubscribeMqttInMessage(0b1011_0000 as byte) def result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result packet.topicFilters.size() == 2 packet.topicFilters.get(0).toString() == topicFilter packet.topicFilters.get(1).toString() == topicFilter2 - packet.packetId == packetId + packet.messageId == packetId packet.userProperties() == userProperties when: dataBuffer = BufferUtils.prepareBuffer(512) { @@ -55,14 +54,14 @@ class UnsubscribeInPacketTest extends BaseInPacketTest { it.putString(topicFilter) it.putString(topicFilter2) } - packet = new UnsubscribeInPacket(0b1011_0000 as byte) + packet = new UnsubscribeMqttInMessage(0b1011_0000 as byte) result = packet.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result packet.topicFilters.size() == 2 packet.topicFilters.get(0).toString() == topicFilter packet.topicFilters.get(1).toString() == topicFilter2 - packet.packetId == packetId + packet.messageId == packetId packet.userProperties() == Array.empty() } } diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/out/Authentication5OutPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/out/AuthenticationMqtt5OutMessageTest.groovy similarity index 70% rename from application/src/test/groovy/javasabr/mqtt/application/network/out/Authentication5OutPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/out/AuthenticationMqtt5OutMessageTest.groovy index e0c4cb38..ed750305 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/out/Authentication5OutPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/out/AuthenticationMqtt5OutMessageTest.groovy @@ -1,15 +1,14 @@ -package javasabr.mqtt.application.network.out +package javasabr.mqtt.network.message.out import javasabr.mqtt.model.reason.code.AuthenticateReasonCode -import javasabr.mqtt.network.packet.in.AuthenticationInPacket -import javasabr.mqtt.network.packet.out.Authentication5OutPacket +import javasabr.mqtt.network.message.in.AuthenticationMqttInMessage import javasabr.rlib.common.util.BufferUtils -class Authentication5OutPacketTest extends BaseOutPacketTest { +class AuthenticationMqtt5OutMessageTest extends BaseMqttOutMessageTest { def "should write packet correctly"() { given: - def packet = new Authentication5OutPacket( + def packet = new AuthenticationMqtt5OutMessage( userProperties, AuthenticateReasonCode.CONTINUE_AUTHENTICATION, reasonString, @@ -19,7 +18,7 @@ class Authentication5OutPacketTest extends BaseOutPacketTest { def dataBuffer = BufferUtils.prepareBuffer(512) { packet.write(defaultMqtt5Connection, it) } - def reader = new AuthenticationInPacket(0b1111_0000 as byte) + def reader = new AuthenticationMqttInMessage(0b1111_0000 as byte) def result = reader.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result diff --git a/network/src/test/groovy/javasabr/mqtt/network/message/out/BaseMqttOutMessageTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/out/BaseMqttOutMessageTest.groovy new file mode 100644 index 00000000..b2d9dd7b --- /dev/null +++ b/network/src/test/groovy/javasabr/mqtt/network/message/out/BaseMqttOutMessageTest.groovy @@ -0,0 +1,7 @@ +package javasabr.mqtt.network.message.out + +import javasabr.mqtt.network.NetworkUnitSpecification + +class BaseMqttOutMessageTest extends NetworkUnitSpecification { + +} diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/out/ConnectAck311OutPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/out/ConnectAckMqtt311OutMessageTest.groovy similarity index 84% rename from application/src/test/groovy/javasabr/mqtt/application/network/out/ConnectAck311OutPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/out/ConnectAckMqtt311OutMessageTest.groovy index 8d2736bd..16cd9e97 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/out/ConnectAck311OutPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/out/ConnectAckMqtt311OutMessageTest.groovy @@ -1,25 +1,24 @@ -package javasabr.mqtt.application.network.out +package javasabr.mqtt.network.message.out import javasabr.mqtt.model.MqttProperties import javasabr.mqtt.model.reason.code.ConnectAckReasonCode -import javasabr.mqtt.network.packet.in.ConnectAckInPacket -import javasabr.mqtt.network.packet.out.ConnectAck311OutPacket +import javasabr.mqtt.network.message.in.ConnectAckMqttInMessage import javasabr.rlib.collections.array.Array import javasabr.rlib.common.util.ArrayUtils import javasabr.rlib.common.util.BufferUtils -class ConnectAck311OutPacketTest extends BaseOutPacketTest { +class ConnectAckMqtt311OutMessageTest extends BaseMqttOutMessageTest { def "should write packet correctly"() { given: - def packet = new ConnectAck311OutPacket( + def packet = new ConnectAckMqtt311OutMessage( ConnectAckReasonCode.BAD_USER_NAME_OR_PASSWORD, sessionPresent) when: def dataBuffer = BufferUtils.prepareBuffer(512) { packet.write(defaultMqtt311Connection, it) } - def reader = new ConnectAckInPacket(0b0010_0000 as byte) + def reader = new ConnectAckMqttInMessage(0b0010_0000 as byte) def result = reader.read(defaultMqtt311Connection, dataBuffer, dataBuffer.limit()) then: result diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/out/ConnectAck5OutPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/out/ConnectAckMqtt5OutMessageTest.groovy similarity index 87% rename from application/src/test/groovy/javasabr/mqtt/application/network/out/ConnectAck5OutPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/out/ConnectAckMqtt5OutMessageTest.groovy index 0e9153ba..aed36f39 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/out/ConnectAck5OutPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/out/ConnectAckMqtt5OutMessageTest.groovy @@ -1,12 +1,11 @@ -package javasabr.mqtt.application.network.out +package javasabr.mqtt.network.message.out import javasabr.mqtt.model.MqttVersion import javasabr.mqtt.model.reason.code.ConnectAckReasonCode -import javasabr.mqtt.network.packet.in.ConnectAckInPacket -import javasabr.mqtt.network.packet.out.ConnectAck5OutPacket +import javasabr.mqtt.network.message.in.ConnectAckMqttInMessage import javasabr.rlib.common.util.BufferUtils -class ConnectAck5OutPacketTest extends BaseOutPacketTest { +class ConnectAckMqtt5OutMessageTest extends BaseMqttOutMessageTest { def "should write packet correctly"() { given: @@ -29,7 +28,7 @@ class ConnectAck5OutPacketTest extends BaseOutPacketTest { def requestedSessionExpireInterval = 360 def requestedKeepAlive = 120 def requestedReceiveMaxPublishes = 500 - def packet = new ConnectAck5OutPacket( + def packet = new ConnectAckMqtt5OutMessage( clientConfig, ConnectAckReasonCode.BAD_USER_NAME_OR_PASSWORD, sessionPresent, @@ -48,7 +47,7 @@ class ConnectAck5OutPacketTest extends BaseOutPacketTest { def dataBuffer = BufferUtils.prepareBuffer(512) { packet.write(defaultMqtt5Connection, it) } - def reader = new ConnectAckInPacket(0b0010_0000 as byte) + def reader = new ConnectAckMqttInMessage(0b0010_0000 as byte) def result = reader.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/out/Connect311OutPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/out/ConnectMqtt311OutMessageTest.groovy similarity index 75% rename from application/src/test/groovy/javasabr/mqtt/application/network/out/Connect311OutPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/out/ConnectMqtt311OutMessageTest.groovy index eb0583db..289adda3 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/out/Connect311OutPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/out/ConnectMqtt311OutMessageTest.groovy @@ -1,17 +1,16 @@ -package javasabr.mqtt.application.network.out +package javasabr.mqtt.network.message.out import javasabr.mqtt.model.QoS -import javasabr.mqtt.network.packet.in.ConnectInPacket -import javasabr.mqtt.network.packet.out.Connect311OutPacket +import javasabr.mqtt.network.message.in.ConnectMqttInMessage import javasabr.rlib.collections.array.Array import javasabr.rlib.common.util.ArrayUtils import javasabr.rlib.common.util.BufferUtils -class Connect311OutPacketTest extends BaseOutPacketTest { +class ConnectMqtt311OutMessageTest extends BaseMqttOutMessageTest { def "should write packet correctly"() { given: - def packet = new Connect311OutPacket( + def packet = new ConnectMqtt311OutMessage( userName, "", mqtt311ClientId, @@ -25,7 +24,7 @@ class Connect311OutPacketTest extends BaseOutPacketTest { def dataBuffer = BufferUtils.prepareBuffer(512) { packet.write(defaultMqtt311Connection, it) } - def reader = new ConnectInPacket(0b0001_0000 as byte) + def reader = new ConnectMqttInMessage(0b0001_0000 as byte) def result = reader.read(defaultMqtt311Connection, dataBuffer, dataBuffer.limit()) then: result diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/out/Connect5OutPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/out/ConnectMqtt5OutMessageTest.groovy similarity index 84% rename from application/src/test/groovy/javasabr/mqtt/application/network/out/Connect5OutPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/out/ConnectMqtt5OutMessageTest.groovy index 0401c17e..e332bbf0 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/out/Connect5OutPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/out/ConnectMqtt5OutMessageTest.groovy @@ -1,16 +1,15 @@ -package javasabr.mqtt.application.network.out +package javasabr.mqtt.network.message.out import javasabr.mqtt.model.QoS -import javasabr.mqtt.network.packet.in.ConnectInPacket -import javasabr.mqtt.network.packet.out.Connect5OutPacket +import javasabr.mqtt.network.message.in.ConnectMqttInMessage import javasabr.rlib.common.util.ArrayUtils import javasabr.rlib.common.util.BufferUtils -class Connect5OutPacketTest extends BaseOutPacketTest { +class ConnectMqtt5OutMessageTest extends BaseMqttOutMessageTest { def "should write packet correctly"() { given: - def packet = new Connect5OutPacket( + def packet = new ConnectMqtt5OutMessage( userName, "", mqtt311ClientId, @@ -33,7 +32,7 @@ class Connect5OutPacketTest extends BaseOutPacketTest { def dataBuffer = BufferUtils.prepareBuffer(512) { packet.write(defaultMqtt5Connection, it) } - def reader = new ConnectInPacket(0b0001_0000 as byte) + def reader = new ConnectMqttInMessage(0b0001_0000 as byte) def result = reader.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/out/DisconnectAck5OutPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/out/DisconnectAckMqtt5OutMessageTest.groovy similarity index 71% rename from application/src/test/groovy/javasabr/mqtt/application/network/out/DisconnectAck5OutPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/out/DisconnectAckMqtt5OutMessageTest.groovy index c601b812..d0ef9041 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/out/DisconnectAck5OutPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/out/DisconnectAckMqtt5OutMessageTest.groovy @@ -1,15 +1,14 @@ -package javasabr.mqtt.application.network.out +package javasabr.mqtt.network.message.out import javasabr.mqtt.model.reason.code.DisconnectReasonCode -import javasabr.mqtt.network.packet.in.DisconnectInPacket -import javasabr.mqtt.network.packet.out.Disconnect5OutPacket +import javasabr.mqtt.network.message.in.DisconnectMqttInMessage import javasabr.rlib.common.util.BufferUtils -class DisconnectAck5OutPacketTest extends BaseOutPacketTest { +class DisconnectAckMqtt5OutMessageTest extends BaseMqttOutMessageTest { def "should write packet correctly"() { given: - def packet = new Disconnect5OutPacket( + def packet = new DisconnectMqtt5OutMessage( DisconnectReasonCode.PACKET_TOO_LARGE, userProperties, reasonString, @@ -19,7 +18,7 @@ class DisconnectAck5OutPacketTest extends BaseOutPacketTest { def dataBuffer = BufferUtils.prepareBuffer(512) { packet.write(defaultMqtt5Connection, it) } - def reader = new DisconnectInPacket(0b1110_0000 as byte) + def reader = new DisconnectMqttInMessage(0b1110_0000 as byte) def result = reader.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/out/PublishAck311OutPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/out/PublishAckMqtt311OutMessageTest.groovy similarity index 60% rename from application/src/test/groovy/javasabr/mqtt/application/network/out/PublishAck311OutPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/out/PublishAckMqtt311OutMessageTest.groovy index c5073ff5..e3468ba6 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/out/PublishAck311OutPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/out/PublishAckMqtt311OutMessageTest.groovy @@ -1,26 +1,25 @@ -package javasabr.mqtt.application.network.out +package javasabr.mqtt.network.message.out import javasabr.mqtt.model.reason.code.PublishAckReasonCode -import javasabr.mqtt.network.packet.in.PublishAckInPacket -import javasabr.mqtt.network.packet.out.PublishAck311OutPacket +import javasabr.mqtt.network.message.in.PublishAckMqttInMessage import javasabr.rlib.collections.array.Array import javasabr.rlib.common.util.BufferUtils -class PublishAck311OutPacketTest extends BaseOutPacketTest { +class PublishAckMqtt311OutMessageTest extends BaseMqttOutMessageTest { def "should write packet correctly"() { given: - def packet = new PublishAck311OutPacket(packetId) + def packet = new PublishAckMqtt311OutMessage(packetId) when: def dataBuffer = BufferUtils.prepareBuffer(512) { packet.write(defaultMqtt311Connection, it) } - def reader = new PublishAckInPacket(0b0100_0000 as byte) + def reader = new PublishAckMqttInMessage(0b0100_0000 as byte) def result = reader.read(defaultMqtt311Connection, dataBuffer, dataBuffer.limit()) then: result reader.reasonCode() == PublishAckReasonCode.SUCCESS - reader.packetId() == packetId + reader.messageId() == packetId reader.userProperties() == Array.empty() reader.reason() == "" } diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/out/PublishAck5OutPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/out/PublishAckMqtt5OutMessageTest.groovy similarity index 64% rename from application/src/test/groovy/javasabr/mqtt/application/network/out/PublishAck5OutPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/out/PublishAckMqtt5OutMessageTest.groovy index 2baaeba9..49e49328 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/out/PublishAck5OutPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/out/PublishAckMqtt5OutMessageTest.groovy @@ -1,15 +1,14 @@ -package javasabr.mqtt.application.network.out +package javasabr.mqtt.network.message.out import javasabr.mqtt.model.reason.code.PublishAckReasonCode -import javasabr.mqtt.network.packet.in.PublishAckInPacket -import javasabr.mqtt.network.packet.out.PublishAck5OutPacket +import javasabr.mqtt.network.message.in.PublishAckMqttInMessage import javasabr.rlib.common.util.BufferUtils -class PublishAck5OutPacketTest extends BaseOutPacketTest { +class PublishAckMqtt5OutMessageTest extends BaseMqttOutMessageTest { def "should write packet correctly"() { given: - def packet = new PublishAck5OutPacket( + def packet = new PublishAckMqtt5OutMessage( packetId, PublishAckReasonCode.NOT_AUTHORIZED, userProperties, @@ -18,12 +17,12 @@ class PublishAck5OutPacketTest extends BaseOutPacketTest { def dataBuffer = BufferUtils.prepareBuffer(512) { packet.write(defaultMqtt5Connection, it) } - def reader = new PublishAckInPacket(0b0100_0000 as byte) + def reader = new PublishAckMqttInMessage(0b0100_0000 as byte) def result = reader.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result reader.reasonCode() == PublishAckReasonCode.NOT_AUTHORIZED - reader.packetId() == packetId + reader.messageId() == packetId reader.userProperties() == userProperties reader.reason() == reasonString } diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/out/PublishComplete311OutPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/out/PublishCompleteMqtt311OutMessageTest.groovy similarity index 59% rename from application/src/test/groovy/javasabr/mqtt/application/network/out/PublishComplete311OutPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/out/PublishCompleteMqtt311OutMessageTest.groovy index 89acce50..3955c856 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/out/PublishComplete311OutPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/out/PublishCompleteMqtt311OutMessageTest.groovy @@ -1,26 +1,25 @@ -package javasabr.mqtt.application.network.out +package javasabr.mqtt.network.message.out import javasabr.mqtt.model.reason.code.PublishCompletedReasonCode -import javasabr.mqtt.network.packet.in.PublishCompleteInPacket -import javasabr.mqtt.network.packet.out.PublishComplete311OutPacket +import javasabr.mqtt.network.message.in.PublishCompleteMqttInMessage import javasabr.rlib.collections.array.Array import javasabr.rlib.common.util.BufferUtils -class PublishComplete311OutPacketTest extends BaseOutPacketTest { +class PublishCompleteMqtt311OutMessageTest extends BaseMqttOutMessageTest { def "should write packet correctly"() { given: - def packet = new PublishComplete311OutPacket(packetId) + def packet = new PublishCompleteMqtt311OutMessage(packetId) when: def dataBuffer = BufferUtils.prepareBuffer(512) { packet.write(defaultMqtt311Connection, it) } - def reader = new PublishCompleteInPacket(0b0111_0000 as byte) + def reader = new PublishCompleteMqttInMessage(0b0111_0000 as byte) def result = reader.read(defaultMqtt311Connection, dataBuffer, dataBuffer.limit()) then: result reader.reasonCode() == PublishCompletedReasonCode.SUCCESS - reader.packetId() == packetId + reader.messageId() == packetId reader.userProperties() == Array.empty() reader.reason() == "" } diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/out/PublishComplete5OutPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/out/PublishCompleteMqtt5OutMessageTest.groovy similarity index 64% rename from application/src/test/groovy/javasabr/mqtt/application/network/out/PublishComplete5OutPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/out/PublishCompleteMqtt5OutMessageTest.groovy index f3513cd0..2958b85c 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/out/PublishComplete5OutPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/out/PublishCompleteMqtt5OutMessageTest.groovy @@ -1,15 +1,14 @@ -package javasabr.mqtt.application.network.out +package javasabr.mqtt.network.message.out import javasabr.mqtt.model.reason.code.PublishCompletedReasonCode -import javasabr.mqtt.network.packet.in.PublishCompleteInPacket -import javasabr.mqtt.network.packet.out.PublishComplete5OutPacket +import javasabr.mqtt.network.message.in.PublishCompleteMqttInMessage import javasabr.rlib.common.util.BufferUtils -class PublishComplete5OutPacketTest extends BaseOutPacketTest { +class PublishCompleteMqtt5OutMessageTest extends BaseMqttOutMessageTest { def "should write packet correctly"() { given: - def packet = new PublishComplete5OutPacket( + def packet = new PublishCompleteMqtt5OutMessage( packetId, PublishCompletedReasonCode.PACKET_IDENTIFIER_NOT_FOUND, userProperties, @@ -18,12 +17,12 @@ class PublishComplete5OutPacketTest extends BaseOutPacketTest { def dataBuffer = BufferUtils.prepareBuffer(512) { packet.write(defaultMqtt5Connection, it) } - def reader = new PublishCompleteInPacket(0b0111_0000 as byte) + def reader = new PublishCompleteMqttInMessage(0b0111_0000 as byte) def result = reader.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result reader.reasonCode() == PublishCompletedReasonCode.PACKET_IDENTIFIER_NOT_FOUND - reader.packetId() == packetId + reader.messageId() == packetId reader.userProperties() == userProperties reader.reason() == reasonString } diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/out/Publish311OutPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/out/PublishMqtt311OutMessageTest.groovy similarity index 74% rename from application/src/test/groovy/javasabr/mqtt/application/network/out/Publish311OutPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/out/PublishMqtt311OutMessageTest.groovy index c86d65e9..6e885d4e 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/out/Publish311OutPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/out/PublishMqtt311OutMessageTest.groovy @@ -1,16 +1,15 @@ -package javasabr.mqtt.application.network.out +package javasabr.mqtt.network.message.out import javasabr.mqtt.model.QoS -import javasabr.mqtt.network.packet.in.PublishInPacket -import javasabr.mqtt.network.packet.out.Publish311OutPacket +import javasabr.mqtt.network.message.in.PublishMqttInMessage import javasabr.rlib.collections.array.Array import javasabr.rlib.common.util.BufferUtils -class Publish311OutPacketTest extends BaseOutPacketTest { +class PublishMqtt311OutMessageTest extends BaseMqttOutMessageTest { def "should write packet correctly"() { given: - def packet = new Publish311OutPacket( + def packet = new PublishMqtt311OutMessage( packetId, QoS.EXACTLY_ONCE, true, @@ -21,11 +20,11 @@ class Publish311OutPacketTest extends BaseOutPacketTest { def dataBuffer = BufferUtils.prepareBuffer(512) { packet.write(defaultMqtt311Connection, it) } - def reader = new PublishInPacket(0b0011_1101 as byte) + def reader = new PublishMqttInMessage(0b0011_1101 as byte) def result = reader.read(defaultMqtt311Connection, dataBuffer, dataBuffer.limit()) then: result - reader.packetId == packetId + reader.messageId == packetId reader.qos == QoS.EXACTLY_ONCE reader.retained reader.duplicate @@ -33,7 +32,7 @@ class Publish311OutPacketTest extends BaseOutPacketTest { reader.topicName == publishTopic reader.userProperties() == Array.empty() when: - packet = new Publish311OutPacket( + packet = new PublishMqtt311OutMessage( packetId, QoS.AT_MOST_ONCE, false, @@ -43,11 +42,11 @@ class Publish311OutPacketTest extends BaseOutPacketTest { dataBuffer = BufferUtils.prepareBuffer(512) { packet.write(defaultMqtt311Connection, it) } - reader = new PublishInPacket(0b0011_0000 as byte) + reader = new PublishMqttInMessage(0b0011_0000 as byte) result = reader.read(defaultMqtt311Connection, dataBuffer, dataBuffer.limit()) then: result - reader.packetId == 0 + reader.messageId == 0 reader.qos == QoS.AT_MOST_ONCE !reader.retained !reader.duplicate diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/out/Publish5OutPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/out/PublishMqtt5OutMessageTest.groovy similarity index 80% rename from application/src/test/groovy/javasabr/mqtt/application/network/out/Publish5OutPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/out/PublishMqtt5OutMessageTest.groovy index 3840079e..96fc7eaf 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/out/Publish5OutPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/out/PublishMqtt5OutMessageTest.groovy @@ -1,15 +1,14 @@ -package javasabr.mqtt.application.network.out +package javasabr.mqtt.network.message.out import javasabr.mqtt.model.QoS -import javasabr.mqtt.network.packet.in.PublishInPacket -import javasabr.mqtt.network.packet.out.Publish5OutPacket +import javasabr.mqtt.network.message.in.PublishMqttInMessage import javasabr.rlib.common.util.BufferUtils -class Publish5OutPacketTest extends BaseOutPacketTest { +class PublishMqtt5OutMessageTest extends BaseMqttOutMessageTest { def "should write packet correctly"() { given: - def packet = new Publish5OutPacket( + def packet = new PublishMqtt5OutMessage( packetId, QoS.EXACTLY_ONCE, true, @@ -25,11 +24,11 @@ class Publish5OutPacketTest extends BaseOutPacketTest { def dataBuffer = BufferUtils.prepareBuffer(512) { packet.write(defaultMqtt5Connection, it) } - def reader = new PublishInPacket(0b0011_1101 as byte) + def reader = new PublishMqttInMessage(0b0011_1101 as byte) def result = reader.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result - reader.packetId == packetId + reader.messageId == packetId reader.qos == QoS.EXACTLY_ONCE reader.retained reader.duplicate @@ -41,7 +40,7 @@ class Publish5OutPacketTest extends BaseOutPacketTest { reader.responseTopic == responseTopic reader.correlationData == correlationData when: - packet = new Publish5OutPacket( + packet = new PublishMqtt5OutMessage( packetId, QoS.AT_MOST_ONCE, false, @@ -58,11 +57,11 @@ class Publish5OutPacketTest extends BaseOutPacketTest { packet.write(defaultMqtt5Connection, it) } - reader = new PublishInPacket(0b0011_0000 as byte) + reader = new PublishMqttInMessage(0b0011_0000 as byte) result = reader.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result - reader.packetId == 0 + reader.messageId == 0 reader.qos == QoS.AT_MOST_ONCE !reader.retained !reader.duplicate diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/out/PublishReceived311OutPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/out/PublishReceivedMqtt311OutMessageTest.groovy similarity index 61% rename from application/src/test/groovy/javasabr/mqtt/application/network/out/PublishReceived311OutPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/out/PublishReceivedMqtt311OutMessageTest.groovy index af8cc46e..c4b036f7 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/out/PublishReceived311OutPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/out/PublishReceivedMqtt311OutMessageTest.groovy @@ -1,27 +1,26 @@ -package javasabr.mqtt.application.network.out +package javasabr.mqtt.network.message.out import javasabr.mqtt.model.data.type.StringPair import javasabr.mqtt.model.reason.code.PublishReceivedReasonCode -import javasabr.mqtt.network.packet.in.PublishReceivedInPacket -import javasabr.mqtt.network.packet.out.PublishReceived311OutPacket +import javasabr.mqtt.network.message.in.PublishReceivedMqttInMessage import javasabr.rlib.collections.array.Array import javasabr.rlib.common.util.BufferUtils -class PublishReceived311OutPacketTest extends BaseOutPacketTest { +class PublishReceivedMqtt311OutMessageTest extends BaseMqttOutMessageTest { def "should write packet correctly"() { given: - def packet = new PublishReceived311OutPacket(packetId) + def packet = new PublishReceivedMqtt311OutMessage(packetId) when: def dataBuffer = BufferUtils.prepareBuffer(512) { packet.write(defaultMqtt311Connection, it) } - def reader = new PublishReceivedInPacket(0b0101_0000 as byte) + def reader = new PublishReceivedMqttInMessage(0b0101_0000 as byte) def result = reader.read(defaultMqtt311Connection, dataBuffer, dataBuffer.limit()) then: result reader.reasonCode() == PublishReceivedReasonCode.SUCCESS - reader.packetId() == packetId + reader.messageId() == packetId reader.userProperties() == Array.empty(StringPair) reader.reason() == "" } diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/out/PublishReceived5OutPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/out/PublishReceivedMqtt5OutMessageTest.groovy similarity index 64% rename from application/src/test/groovy/javasabr/mqtt/application/network/out/PublishReceived5OutPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/out/PublishReceivedMqtt5OutMessageTest.groovy index 3b8343be..837aa90c 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/out/PublishReceived5OutPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/out/PublishReceivedMqtt5OutMessageTest.groovy @@ -1,15 +1,14 @@ -package javasabr.mqtt.application.network.out +package javasabr.mqtt.network.message.out import javasabr.mqtt.model.reason.code.PublishReceivedReasonCode -import javasabr.mqtt.network.packet.in.PublishReceivedInPacket -import javasabr.mqtt.network.packet.out.PublishReceived5OutPacket +import javasabr.mqtt.network.message.in.PublishReceivedMqttInMessage import javasabr.rlib.common.util.BufferUtils -class PublishReceived5OutPacketTest extends BaseOutPacketTest { +class PublishReceivedMqtt5OutMessageTest extends BaseMqttOutMessageTest { def "should write packet correctly"() { given: - def packet = new PublishReceived5OutPacket( + def packet = new PublishReceivedMqtt5OutMessage( packetId, PublishReceivedReasonCode.UNSPECIFIED_ERROR, userProperties, @@ -18,12 +17,12 @@ class PublishReceived5OutPacketTest extends BaseOutPacketTest { def dataBuffer = BufferUtils.prepareBuffer(512) { packet.write(defaultMqtt5Connection, it) } - def reader = new PublishReceivedInPacket(0b0101_0000 as byte) + def reader = new PublishReceivedMqttInMessage(0b0101_0000 as byte) def result = reader.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result reader.reasonCode() == PublishReceivedReasonCode.UNSPECIFIED_ERROR - reader.packetId() == packetId + reader.messageId() == packetId reader.userProperties() == userProperties reader.reason() == reasonString } diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/out/PublishRelease311OutPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/out/PublishReleaseMqtt311OutMessageTest.groovy similarity index 61% rename from application/src/test/groovy/javasabr/mqtt/application/network/out/PublishRelease311OutPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/out/PublishReleaseMqtt311OutMessageTest.groovy index 5dbd404e..92424cac 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/out/PublishRelease311OutPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/out/PublishReleaseMqtt311OutMessageTest.groovy @@ -1,27 +1,26 @@ -package javasabr.mqtt.application.network.out +package javasabr.mqtt.network.message.out import javasabr.mqtt.model.data.type.StringPair import javasabr.mqtt.model.reason.code.PublishReleaseReasonCode -import javasabr.mqtt.network.packet.in.PublishReleaseInPacket -import javasabr.mqtt.network.packet.out.PublishRelease311OutPacket +import javasabr.mqtt.network.message.in.PublishReleaseMqttInMessage import javasabr.rlib.collections.array.Array import javasabr.rlib.common.util.BufferUtils -class PublishRelease311OutPacketTest extends BaseOutPacketTest { +class PublishReleaseMqtt311OutMessageTest extends BaseMqttOutMessageTest { def "should write packet correctly"() { given: - def packet = new PublishRelease311OutPacket(packetId) + def packet = new PublishReleaseMqtt311OutMessage(packetId) when: def dataBuffer = BufferUtils.prepareBuffer(512) { packet.write(defaultMqtt311Connection, it) } - def reader = new PublishReleaseInPacket(0b0110_0000 as byte) + def reader = new PublishReleaseMqttInMessage(0b0110_0000 as byte) def result = reader.read(defaultMqtt311Connection, dataBuffer, dataBuffer.limit()) then: result reader.reasonCode() == PublishReleaseReasonCode.SUCCESS - reader.packetId() == packetId + reader.messageId() == packetId reader.userProperties() == Array.empty(StringPair) reader.reason() == "" } diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/out/PublishRelease5OutPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/out/PublishReleaseMqtt5OutMessageTest.groovy similarity index 64% rename from application/src/test/groovy/javasabr/mqtt/application/network/out/PublishRelease5OutPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/out/PublishReleaseMqtt5OutMessageTest.groovy index 23b272bf..d59263de 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/out/PublishRelease5OutPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/out/PublishReleaseMqtt5OutMessageTest.groovy @@ -1,15 +1,14 @@ -package javasabr.mqtt.application.network.out +package javasabr.mqtt.network.message.out import javasabr.mqtt.model.reason.code.PublishReleaseReasonCode -import javasabr.mqtt.network.packet.in.PublishReleaseInPacket -import javasabr.mqtt.network.packet.out.PublishRelease5OutPacket +import javasabr.mqtt.network.message.in.PublishReleaseMqttInMessage import javasabr.rlib.common.util.BufferUtils -class PublishRelease5OutPacketTest extends BaseOutPacketTest { +class PublishReleaseMqtt5OutMessageTest extends BaseMqttOutMessageTest { def "should write packet correctly"() { given: - def packet = new PublishRelease5OutPacket( + def packet = new PublishReleaseMqtt5OutMessage( packetId, PublishReleaseReasonCode.PACKET_IDENTIFIER_NOT_FOUND, userProperties, @@ -18,12 +17,12 @@ class PublishRelease5OutPacketTest extends BaseOutPacketTest { def dataBuffer = BufferUtils.prepareBuffer(512) { packet.write(defaultMqtt5Connection, it) } - def reader = new PublishReleaseInPacket(0b0110_0000 as byte) + def reader = new PublishReleaseMqttInMessage(0b0110_0000 as byte) def result = reader.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result reader.reasonCode() == PublishReleaseReasonCode.PACKET_IDENTIFIER_NOT_FOUND - reader.packetId() == packetId + reader.messageId() == packetId reader.userProperties() == userProperties reader.reason() == reasonString } diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/out/SubscribeAck311OutPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/out/SubscribeAckMqtt311OutMessageTest.groovy similarity index 58% rename from application/src/test/groovy/javasabr/mqtt/application/network/out/SubscribeAck311OutPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/out/SubscribeAckMqtt311OutMessageTest.groovy index c88aac01..0ca18cc7 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/out/SubscribeAck311OutPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/out/SubscribeAckMqtt311OutMessageTest.groovy @@ -1,26 +1,25 @@ -package javasabr.mqtt.application.network.out +package javasabr.mqtt.network.message.out import javasabr.mqtt.model.data.type.StringPair -import javasabr.mqtt.network.packet.in.SubscribeAckInPacket -import javasabr.mqtt.network.packet.out.SubscribeAck311OutPacket +import javasabr.mqtt.network.message.in.SubscribeAckMqttInMessage import javasabr.rlib.collections.array.Array import javasabr.rlib.common.util.BufferUtils -class SubscribeAck311OutPacketTest extends BaseOutPacketTest { +class SubscribeAckMqtt311OutMessageTest extends BaseMqttOutMessageTest { def "should write packet correctly"() { given: - def packet = new SubscribeAck311OutPacket(subscribeAckReasonCodes, packetId) + def packet = new SubscribeAckMqtt311OutMessage(subscribeAckReasonCodes, packetId) when: def dataBuffer = BufferUtils.prepareBuffer(512) { packet.write(defaultMqtt311Connection, it) } - def reader = new SubscribeAckInPacket(0b1001_0000 as byte) + def reader = new SubscribeAckMqttInMessage(0b1001_0000 as byte) def result = reader.read(defaultMqtt311Connection, dataBuffer, dataBuffer.limit()) then: result reader.reasonCodes == subscribeAckReasonCodes - reader.packetId == packetId + reader.messageId == packetId reader.userProperties() == Array.empty(StringPair) reader.reason == "" } diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/out/SubscribeAck5OutPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/out/SubscribeAckMqtt5OutMessageTest.groovy similarity index 61% rename from application/src/test/groovy/javasabr/mqtt/application/network/out/SubscribeAck5OutPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/out/SubscribeAckMqtt5OutMessageTest.groovy index deadb2cd..09a33110 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/out/SubscribeAck5OutPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/out/SubscribeAckMqtt5OutMessageTest.groovy @@ -1,14 +1,13 @@ -package javasabr.mqtt.application.network.out +package javasabr.mqtt.network.message.out -import javasabr.mqtt.network.packet.in.SubscribeAckInPacket -import javasabr.mqtt.network.packet.out.SubscribeAck5OutPacket +import javasabr.mqtt.network.message.in.SubscribeAckMqttInMessage import javasabr.rlib.common.util.BufferUtils -class SubscribeAck5OutPacketTest extends BaseOutPacketTest { +class SubscribeAckMqtt5OutMessageTest extends BaseMqttOutMessageTest { def "should write packet correctly"() { given: - def packet = new SubscribeAck5OutPacket( + def packet = new SubscribeAckMqtt5OutMessage( packetId, subscribeAckReasonCodes, userProperties, @@ -17,12 +16,12 @@ class SubscribeAck5OutPacketTest extends BaseOutPacketTest { def dataBuffer = BufferUtils.prepareBuffer(512) { packet.write(defaultMqtt5Connection, it) } - def reader = new SubscribeAckInPacket(0b1001_0000 as byte) + def reader = new SubscribeAckMqttInMessage(0b1001_0000 as byte) def result = reader.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result reader.reasonCodes == subscribeAckReasonCodes - reader.packetId == packetId + reader.messageId == packetId reader.userProperties() == userProperties reader.reason == reasonString } diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/out/Subscribe311OutPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/out/SubscribeMqtt311OutMessageTest.groovy similarity index 66% rename from application/src/test/groovy/javasabr/mqtt/application/network/out/Subscribe311OutPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/out/SubscribeMqtt311OutMessageTest.groovy index 7a38ccc8..ccdd7c5a 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/out/Subscribe311OutPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/out/SubscribeMqtt311OutMessageTest.groovy @@ -1,28 +1,27 @@ -package javasabr.mqtt.application.network.out +package javasabr.mqtt.network.message.out import javasabr.mqtt.model.MqttProperties import javasabr.mqtt.model.data.type.StringPair -import javasabr.mqtt.network.packet.in.SubscribeInPacket -import javasabr.mqtt.network.packet.out.Subscribe311OutPacket +import javasabr.mqtt.network.message.in.SubscribeMqttInMessage import javasabr.rlib.collections.array.Array import javasabr.rlib.common.util.BufferUtils -class Subscribe311OutPacketTest extends BaseOutPacketTest { +class SubscribeMqtt311OutMessageTest extends BaseMqttOutMessageTest { def "should write packet correctly"() { given: - def packet = new Subscribe311OutPacket( + def packet = new SubscribeMqtt311OutMessage( topicFiltersObj311, 1) when: def dataBuffer = BufferUtils.prepareBuffer(512) { packet.write(defaultMqtt311Connection, it) } - def reader = new SubscribeInPacket(0b1000_0000 as byte) + def reader = new SubscribeMqttInMessage(0b1000_0000 as byte) def result = reader.read(defaultMqtt311Connection, dataBuffer, dataBuffer.limit()) then: result - reader.packetId == 1 + reader.messageId == 1 reader.topicFilters == topicFiltersObj311 reader.userProperties() == Array.empty(StringPair) reader.subscriptionId == MqttProperties.SUBSCRIPTION_ID_UNDEFINED diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/out/Subscribe5OutPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/out/SubscribeMqtt5OutMessageTest.groovy similarity index 65% rename from application/src/test/groovy/javasabr/mqtt/application/network/out/Subscribe5OutPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/out/SubscribeMqtt5OutMessageTest.groovy index 35e28516..0373f1e0 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/out/Subscribe5OutPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/out/SubscribeMqtt5OutMessageTest.groovy @@ -1,15 +1,14 @@ -package javasabr.mqtt.application.network.out +package javasabr.mqtt.network.message.out import javasabr.mqtt.model.MqttProperties -import javasabr.mqtt.network.packet.in.SubscribeInPacket -import javasabr.mqtt.network.packet.out.Subscribe5OutPacket +import javasabr.mqtt.network.message.in.SubscribeMqttInMessage import javasabr.rlib.common.util.BufferUtils -class Subscribe5OutPacketTest extends BaseOutPacketTest { +class SubscribeMqtt5OutMessageTest extends BaseMqttOutMessageTest { def "should write packet correctly"() { given: - def packet = new Subscribe5OutPacket( + def packet = new SubscribeMqtt5OutMessage( topicFiltersObj5, 1, userProperties, @@ -18,11 +17,11 @@ class Subscribe5OutPacketTest extends BaseOutPacketTest { def dataBuffer = BufferUtils.prepareBuffer(512) { packet.write(defaultMqtt5Connection, it) } - def reader = new SubscribeInPacket(0b1000_0000 as byte) + def reader = new SubscribeMqttInMessage(0b1000_0000 as byte) def result = reader.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result - reader.packetId == 1 + reader.messageId == 1 reader.topicFilters == topicFiltersObj5 reader.userProperties() == userProperties reader.subscriptionId == MqttProperties.SUBSCRIPTION_ID_UNDEFINED diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/out/UnsubscribeAck311OutPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/out/UnsubscribeAckMqtt311OutMessageTest.groovy similarity index 62% rename from application/src/test/groovy/javasabr/mqtt/application/network/out/UnsubscribeAck311OutPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/out/UnsubscribeAckMqtt311OutMessageTest.groovy index d81f1666..54fe0b69 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/out/UnsubscribeAck311OutPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/out/UnsubscribeAckMqtt311OutMessageTest.groovy @@ -1,27 +1,26 @@ -package javasabr.mqtt.application.network.out +package javasabr.mqtt.network.message.out import javasabr.mqtt.model.data.type.StringPair import javasabr.mqtt.model.reason.code.UnsubscribeAckReasonCode -import javasabr.mqtt.network.packet.in.UnsubscribeAckInPacket -import javasabr.mqtt.network.packet.out.UnsubscribeAck311OutPacket +import javasabr.mqtt.network.message.in.UnsubscribeAckMqttInMessage import javasabr.rlib.collections.array.Array import javasabr.rlib.common.util.BufferUtils -class UnsubscribeAck311OutPacketTest extends BaseOutPacketTest { +class UnsubscribeAckMqtt311OutMessageTest extends BaseMqttOutMessageTest { def "should write packet correctly"() { given: - def packet = new UnsubscribeAck311OutPacket(packetId) + def packet = new UnsubscribeAckMqtt311OutMessage(packetId) when: def dataBuffer = BufferUtils.prepareBuffer(512) { packet.write(defaultMqtt311Connection, it) } - def reader = new UnsubscribeAckInPacket(0b1011_0000 as byte) + def reader = new UnsubscribeAckMqttInMessage(0b1011_0000 as byte) def result = reader.read(defaultMqtt311Connection, dataBuffer, dataBuffer.limit()) then: result reader.reasonCodes() == Array.empty(UnsubscribeAckReasonCode) - reader.packetId() == packetId + reader.messageId() == packetId reader.userProperties() == Array.empty(StringPair) reader.reason() == "" } diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/out/UnsubscribeAck5OutPacketTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/message/out/UnsubscribeAckMqtt5OutMessageTest.groovy similarity index 60% rename from application/src/test/groovy/javasabr/mqtt/application/network/out/UnsubscribeAck5OutPacketTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/message/out/UnsubscribeAckMqtt5OutMessageTest.groovy index a28a8323..0f04821f 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/out/UnsubscribeAck5OutPacketTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/message/out/UnsubscribeAckMqtt5OutMessageTest.groovy @@ -1,14 +1,13 @@ -package javasabr.mqtt.application.network.out +package javasabr.mqtt.network.message.out -import javasabr.mqtt.network.packet.in.UnsubscribeAckInPacket -import javasabr.mqtt.network.packet.out.UnsubscribeAck5OutPacket +import javasabr.mqtt.network.message.in.UnsubscribeAckMqttInMessage import javasabr.rlib.common.util.BufferUtils -class UnsubscribeAck5OutPacketTest extends BaseOutPacketTest { +class UnsubscribeAckMqtt5OutMessageTest extends BaseMqttOutMessageTest { def "should write packet correctly"() { given: - def packet = new UnsubscribeAck5OutPacket( + def packet = new UnsubscribeAckMqtt5OutMessage( packetId, unsubscribeAckReasonCodes, userProperties, @@ -17,12 +16,12 @@ class UnsubscribeAck5OutPacketTest extends BaseOutPacketTest { def dataBuffer = BufferUtils.prepareBuffer(512) { packet.write(defaultMqtt5Connection, it) } - def reader = new UnsubscribeAckInPacket(0b1011_0000 as byte) + def reader = new UnsubscribeAckMqttInMessage(0b1011_0000 as byte) def result = reader.read(defaultMqtt5Connection, dataBuffer, dataBuffer.limit()) then: result reader.reasonCodes() == unsubscribeAckReasonCodes - reader.packetId() == packetId + reader.messageId() == packetId reader.userProperties() == userProperties reader.reason() == reasonString } diff --git a/application/src/test/groovy/javasabr/mqtt/application/util/MqttDataUtilsTest.groovy b/network/src/test/groovy/javasabr/mqtt/network/util/MqttDataUtilsTest.groovy similarity index 92% rename from application/src/test/groovy/javasabr/mqtt/application/util/MqttDataUtilsTest.groovy rename to network/src/test/groovy/javasabr/mqtt/network/util/MqttDataUtilsTest.groovy index 3e10bef8..3a7f75dd 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/util/MqttDataUtilsTest.groovy +++ b/network/src/test/groovy/javasabr/mqtt/network/util/MqttDataUtilsTest.groovy @@ -1,7 +1,7 @@ -package javasabr.mqtt.application.util +package javasabr.mqtt.network.util -import javasabr.mqtt.application.UnitSpecification -import javasabr.mqtt.network.utils.MqttDataUtils + +import javasabr.mqtt.test.support.UnitSpecification import java.nio.ByteBuffer @@ -44,13 +44,10 @@ class MqttDataUtilsTest extends UnitSpecification { def "should failed reading integer from MQTT multi byte integer"(int value, int position) { given: - def buffer = ByteBuffer.allocate(10) - MqttDataUtils.writeMbi(value, buffer) .position(position) .flip() - when: def read = MqttDataUtils.readMbi(buffer) then: diff --git a/application/src/test/groovy/javasabr/mqtt/application/mock/MqttMockClient.groovy b/network/src/testFixtures/groovy/javasabr/mqtt/network/MqttMockClient.groovy similarity index 71% rename from application/src/test/groovy/javasabr/mqtt/application/mock/MqttMockClient.groovy rename to network/src/testFixtures/groovy/javasabr/mqtt/network/MqttMockClient.groovy index bef6c6b0..6f2535d2 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/mock/MqttMockClient.groovy +++ b/network/src/testFixtures/groovy/javasabr/mqtt/network/MqttMockClient.groovy @@ -1,11 +1,10 @@ -package javasabr.mqtt.application.mock - -import javasabr.mqtt.network.MqttConnection -import javasabr.mqtt.network.packet.MqttPacketType -import javasabr.mqtt.network.packet.in.* -import javasabr.mqtt.network.packet.out.Disconnect311OutPacket -import javasabr.mqtt.network.packet.out.MqttWritablePacket -import javasabr.mqtt.network.utils.MqttDataUtils +package javasabr.mqtt.network + +import javasabr.mqtt.network.message.MqttMessageType +import javasabr.mqtt.network.message.in.* +import javasabr.mqtt.network.message.out.DisconnectMqtt311OutMessage +import javasabr.mqtt.network.message.out.MqttOutMessage +import javasabr.mqtt.network.util.MqttDataUtils import javasabr.rlib.common.util.NumberUtils import java.nio.ByteBuffer @@ -33,7 +32,7 @@ class MqttMockClient { socket = new Socket(brokerHost, brokerPort) } - void send(MqttWritablePacket packet) { + void send(MqttOutMessage packet) { def dataBuffer = ByteBuffer.allocate(1024) packet.write(connection, dataBuffer) @@ -52,7 +51,7 @@ class MqttMockClient { Thread.sleep(50) } - MqttReadablePacket readNext() { + MqttInMessage readNext() { if (received.position() == 0) { def input = socket.getInputStream() @@ -73,20 +72,20 @@ class MqttMockClient { def info = NumberUtils.getLowByteBits(startByte) def dataSize = MqttDataUtils.readMbi(received) - MqttReadablePacket packet + MqttInMessage packet - switch (MqttPacketType.fromByte(type)) { - case MqttPacketType.CONNECT_ACK: - packet = new ConnectAckInPacket(info) + switch (MqttMessageType.fromByte(type)) { + case MqttMessageType.CONNECT_ACK: + packet = new ConnectAckMqttInMessage(info) break - case MqttPacketType.SUBSCRIBE_ACK: - packet = new SubscribeAckInPacket(info) + case MqttMessageType.SUBSCRIBE_ACK: + packet = new SubscribeAckMqttInMessage(info) break - case MqttPacketType.PUBLISH: - packet = new PublishInPacket(info) + case MqttMessageType.PUBLISH: + packet = new PublishMqttInMessage(info) break - case MqttPacketType.PUBLISH_RELEASED: - packet = new PublishReleaseInPacket(info) + case MqttMessageType.PUBLISH_RELEASED: + packet = new PublishReleaseMqttInMessage(info) break default: throw new IllegalStateException("Unknown packet of type: $type") @@ -104,7 +103,7 @@ class MqttMockClient { } def disconnect() { - send(new Disconnect311OutPacket()) + send(new DisconnectMqtt311OutMessage()) close() } diff --git a/application/src/test/groovy/javasabr/mqtt/application/network/NetworkUnitSpecification.groovy b/network/src/testFixtures/groovy/javasabr/mqtt/network/NetworkUnitSpecification.groovy similarity index 96% rename from application/src/test/groovy/javasabr/mqtt/application/network/NetworkUnitSpecification.groovy rename to network/src/testFixtures/groovy/javasabr/mqtt/network/NetworkUnitSpecification.groovy index 4392dd19..7f1b8c13 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/network/NetworkUnitSpecification.groovy +++ b/network/src/testFixtures/groovy/javasabr/mqtt/network/NetworkUnitSpecification.groovy @@ -1,13 +1,11 @@ -package javasabr.mqtt.application.network +package javasabr.mqtt.network -import javasabr.mqtt.application.UnitSpecification import javasabr.mqtt.model.* import javasabr.mqtt.model.data.type.StringPair import javasabr.mqtt.model.reason.code.SubscribeAckReasonCode import javasabr.mqtt.model.reason.code.UnsubscribeAckReasonCode import javasabr.mqtt.model.subscriber.SubscribeTopicFilter -import javasabr.mqtt.network.MqttClient -import javasabr.mqtt.network.MqttConnection +import javasabr.mqtt.test.support.UnitSpecification import javasabr.rlib.collections.array.Array import javasabr.rlib.collections.array.IntArray import spock.lang.Shared @@ -15,8 +13,8 @@ import spock.lang.Shared import java.nio.charset.StandardCharsets import java.util.concurrent.atomic.AtomicInteger -import static javasabr.mqtt.model.utils.TopicUtils.buildTopicFilter -import static javasabr.mqtt.model.utils.TopicUtils.buildTopicName +import static javasabr.mqtt.model.util.TopicUtils.buildTopicFilter +import static javasabr.mqtt.model.util.TopicUtils.buildTopicName class NetworkUnitSpecification extends UnitSpecification { @@ -254,7 +252,7 @@ class NetworkUnitSpecification extends UnitSpecification { MqttClientConnectionConfig clientConfig, String clientId) { return Stub(MqttConnection) { - isSupported(_) >> { MqttVersion version -> + isSupported(spock.lang.Specification._) >> { MqttVersion version -> clientConfig.mqttVersion().include(version) } serverConnectionConfig() >> serverConfig diff --git a/application/src/test/groovy/javasabr/mqtt/application/extension/SpecificationExtensions.groovy b/network/src/testFixtures/groovy/javasabr/mqtt/network/SpecificationNetworkExtensions.groovy similarity index 87% rename from application/src/test/groovy/javasabr/mqtt/application/extension/SpecificationExtensions.groovy rename to network/src/testFixtures/groovy/javasabr/mqtt/network/SpecificationNetworkExtensions.groovy index 63f284ff..8772c8e0 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/extension/SpecificationExtensions.groovy +++ b/network/src/testFixtures/groovy/javasabr/mqtt/network/SpecificationNetworkExtensions.groovy @@ -1,20 +1,19 @@ -package javasabr.mqtt.application.extension +package javasabr.mqtt.network import javasabr.mqtt.model.PacketProperty import javasabr.mqtt.model.data.type.PacketDataType import javasabr.mqtt.model.data.type.StringPair -import javasabr.mqtt.network.MqttConnection -import javasabr.mqtt.network.packet.out.MqttWritablePacket -import javasabr.mqtt.network.utils.MqttDataUtils +import javasabr.mqtt.network.message.out.MqttOutMessage +import javasabr.mqtt.network.util.MqttDataUtils import javasabr.rlib.collections.array.Array import javasabr.rlib.collections.array.IntArray import spock.lang.Specification import java.nio.ByteBuffer -class SpecificationExtensions extends Specification { +class SpecificationNetworkExtensions extends Specification { - static final writer = new MqttWritablePacket() { + static final writer = new MqttOutMessage() { @Override protected void writeImpl(MqttConnection connection, ByteBuffer buffer) {} diff --git a/network/src/testFixtures/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule b/network/src/testFixtures/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule new file mode 100644 index 00000000..6e8925ff --- /dev/null +++ b/network/src/testFixtures/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule @@ -0,0 +1,3 @@ +moduleName=network-testFixtures +moduleVersion=1.0 +extensionClasses=javasabr.mqtt.network.SpecificationNetworkExtensions diff --git a/service/src/main/java/javasabr/mqtt/service/PublishDeliveringService.java b/service/src/main/java/javasabr/mqtt/service/PublishDeliveringService.java index 0dada0e0..5463cab9 100644 --- a/service/src/main/java/javasabr/mqtt/service/PublishDeliveringService.java +++ b/service/src/main/java/javasabr/mqtt/service/PublishDeliveringService.java @@ -1,10 +1,10 @@ package javasabr.mqtt.service; import javasabr.mqtt.model.subscriber.SingleSubscriber; -import javasabr.mqtt.network.packet.in.PublishInPacket; +import javasabr.mqtt.network.message.in.PublishMqttInMessage; import javasabr.mqtt.service.publish.handler.PublishHandlingResult; public interface PublishDeliveringService { - PublishHandlingResult startDelivering(PublishInPacket publish, SingleSubscriber subscriber); + PublishHandlingResult startDelivering(PublishMqttInMessage publish, SingleSubscriber subscriber); } diff --git a/service/src/main/java/javasabr/mqtt/service/PublishReceivingService.java b/service/src/main/java/javasabr/mqtt/service/PublishReceivingService.java index 4f4adf2e..371dc2e7 100644 --- a/service/src/main/java/javasabr/mqtt/service/PublishReceivingService.java +++ b/service/src/main/java/javasabr/mqtt/service/PublishReceivingService.java @@ -1,9 +1,9 @@ package javasabr.mqtt.service; import javasabr.mqtt.network.MqttClient; -import javasabr.mqtt.network.packet.in.PublishInPacket; +import javasabr.mqtt.network.message.in.PublishMqttInMessage; public interface PublishReceivingService { - void processReceivedPublish(MqttClient client, PublishInPacket publish); + void processReceivedPublish(MqttClient client, PublishMqttInMessage publish); } diff --git a/service/src/main/java/javasabr/mqtt/service/handler/client/AbstractMqttClientReleaseHandler.java b/service/src/main/java/javasabr/mqtt/service/handler/client/AbstractMqttClientReleaseHandler.java index ce2d9215..9cf9b0d6 100644 --- a/service/src/main/java/javasabr/mqtt/service/handler/client/AbstractMqttClientReleaseHandler.java +++ b/service/src/main/java/javasabr/mqtt/service/handler/client/AbstractMqttClientReleaseHandler.java @@ -2,11 +2,11 @@ import javasabr.mqtt.model.MqttClientConnectionConfig; import javasabr.mqtt.network.MqttClient.UnsafeMqttClient; -import javasabr.mqtt.network.client.AbstractMqttClient; import javasabr.mqtt.network.handler.MqttClientReleaseHandler; +import javasabr.mqtt.network.impl.AbstractMqttClient; import javasabr.mqtt.service.ClientIdRegistry; -import javasabr.mqtt.service.SessionService; import javasabr.mqtt.service.SubscriptionService; +import javasabr.mqtt.service.session.MqttSessionService; import javasabr.rlib.common.util.StringUtils; import lombok.CustomLog; import lombok.RequiredArgsConstructor; @@ -18,7 +18,7 @@ public abstract class AbstractMqttClientReleaseHandler { public ExternalMqttClientReleaseHandler( ClientIdRegistry clientIdRegistry, - SessionService sessionService, + MqttSessionService sessionService, SubscriptionService subscriptionService) { super(clientIdRegistry, sessionService, subscriptionService); } diff --git a/service/src/main/java/javasabr/mqtt/service/impl/DefaultConnectionService.java b/service/src/main/java/javasabr/mqtt/service/impl/DefaultConnectionService.java index cde9860d..30cb8959 100644 --- a/service/src/main/java/javasabr/mqtt/service/impl/DefaultConnectionService.java +++ b/service/src/main/java/javasabr/mqtt/service/impl/DefaultConnectionService.java @@ -2,8 +2,8 @@ import java.util.Collection; import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.MqttPacketType; -import javasabr.mqtt.network.packet.in.MqttReadablePacket; +import javasabr.mqtt.network.message.MqttMessageType; +import javasabr.mqtt.network.message.in.MqttInMessage; import javasabr.mqtt.service.ConnectionService; import javasabr.mqtt.service.message.handler.MqttInMessageHandler; import javasabr.rlib.network.packet.ReadableNetworkPacket; @@ -23,14 +23,14 @@ public DefaultConnectionService(Collection known int highestPacketType = knownInMessageHandlers .stream() .map(MqttInMessageHandler::messageType) - .mapToInt(MqttPacketType::typeIndex) + .mapToInt(MqttMessageType::typeIndex) .max() .orElse(0); var inMessageHandlers = new MqttInMessageHandler[highestPacketType + 1]; for (MqttInMessageHandler knownInMessageHandler : knownInMessageHandlers) { - MqttPacketType messageType = knownInMessageHandler.messageType(); + MqttMessageType messageType = knownInMessageHandler.messageType(); if (inMessageHandlers[messageType.typeIndex()] != null) { throw new IllegalArgumentException("Found duplicate MqttInMessageHandler:[" + knownInMessageHandler + "]"); } @@ -51,7 +51,7 @@ protected void processReceivedMessage( MqttConnection connection, ReadableNetworkPacket networkPacket) { - if (!(networkPacket instanceof MqttReadablePacket mrp)) { + if (!(networkPacket instanceof MqttInMessage mrp)) { log.warning(networkPacket, "Received not processable network packet:[%s]"::formatted); return; } @@ -64,7 +64,7 @@ protected void processReceivedMessage( try { //noinspection DataFlowIssue - inMessageHandlers[mrp.packetType()].processReceived(connection, mrp); + inMessageHandlers[mrp.messageType()].processReceived(connection, mrp); } catch (IndexOutOfBoundsException | NullPointerException ex) { log.warning(mrp, "Received not supported MQTT message:[%s]"::formatted); } diff --git a/service/src/main/java/javasabr/mqtt/service/impl/DefaultPublishDeliveringService.java b/service/src/main/java/javasabr/mqtt/service/impl/DefaultPublishDeliveringService.java index 3a772512..c0f27b11 100644 --- a/service/src/main/java/javasabr/mqtt/service/impl/DefaultPublishDeliveringService.java +++ b/service/src/main/java/javasabr/mqtt/service/impl/DefaultPublishDeliveringService.java @@ -3,7 +3,7 @@ import java.util.Collection; import javasabr.mqtt.model.QoS; import javasabr.mqtt.model.subscriber.SingleSubscriber; -import javasabr.mqtt.network.packet.in.PublishInPacket; +import javasabr.mqtt.network.message.in.PublishMqttInMessage; import javasabr.mqtt.service.PublishDeliveringService; import javasabr.mqtt.service.publish.handler.MqttPublishOutMessageHandler; import javasabr.mqtt.service.publish.handler.PublishHandlingResult; @@ -45,7 +45,7 @@ public DefaultPublishDeliveringService( } @Override - public PublishHandlingResult startDelivering(PublishInPacket publish, SingleSubscriber subscriber) { + public PublishHandlingResult startDelivering(PublishMqttInMessage publish, SingleSubscriber subscriber) { try { //noinspection DataFlowIssue return publishOutMessageHandlers[subscriber.getQos().index()].handle(publish, subscriber); diff --git a/service/src/main/java/javasabr/mqtt/service/impl/DefaultPublishReceivingService.java b/service/src/main/java/javasabr/mqtt/service/impl/DefaultPublishReceivingService.java index 5a14542c..0cd50e08 100644 --- a/service/src/main/java/javasabr/mqtt/service/impl/DefaultPublishReceivingService.java +++ b/service/src/main/java/javasabr/mqtt/service/impl/DefaultPublishReceivingService.java @@ -3,7 +3,7 @@ import java.util.Collection; import javasabr.mqtt.model.QoS; import javasabr.mqtt.network.MqttClient; -import javasabr.mqtt.network.packet.in.PublishInPacket; +import javasabr.mqtt.network.message.in.PublishMqttInMessage; import javasabr.mqtt.service.PublishReceivingService; import javasabr.mqtt.service.publish.handler.MqttPublishInMessageHandler; import lombok.AccessLevel; @@ -44,10 +44,11 @@ public DefaultPublishReceivingService( } @Override - public void processReceivedPublish(MqttClient client, PublishInPacket publish) { + public void processReceivedPublish(MqttClient client, PublishMqttInMessage publish) { + QoS qos = publish.qos(); try { //noinspection DataFlowIssue - publishInHandlers[publish.getQos().index()].handle(client, publish); + publishInHandlers[qos.index()].handle(client, publish); } catch (IndexOutOfBoundsException | NullPointerException ex) { log.warning(publish, "Received not supported publish message:[%s]"::formatted); } diff --git a/service/src/main/java/javasabr/mqtt/service/impl/ExternalMqttClientFactory.java b/service/src/main/java/javasabr/mqtt/service/impl/ExternalMqttClientFactory.java index 38876d1d..666be76f 100644 --- a/service/src/main/java/javasabr/mqtt/service/impl/ExternalMqttClientFactory.java +++ b/service/src/main/java/javasabr/mqtt/service/impl/ExternalMqttClientFactory.java @@ -3,8 +3,8 @@ import javasabr.mqtt.network.MqttClient.UnsafeMqttClient; import javasabr.mqtt.network.MqttClientFactory; import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.client.ExternalMqttClient; import javasabr.mqtt.network.handler.MqttClientReleaseHandler; +import javasabr.mqtt.network.impl.ExternalMqttClient; import lombok.AccessLevel; import lombok.RequiredArgsConstructor; import lombok.experimental.FieldDefaults; diff --git a/service/src/main/java/javasabr/mqtt/service/impl/SimpleSubscriptionService.java b/service/src/main/java/javasabr/mqtt/service/impl/SimpleSubscriptionService.java index 78beac17..2d1ee4bf 100644 --- a/service/src/main/java/javasabr/mqtt/service/impl/SimpleSubscriptionService.java +++ b/service/src/main/java/javasabr/mqtt/service/impl/SimpleSubscriptionService.java @@ -7,8 +7,8 @@ import static javasabr.mqtt.model.reason.code.SubscribeAckReasonCode.WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED; import static javasabr.mqtt.model.reason.code.UnsubscribeAckReasonCode.NO_SUBSCRIPTION_EXISTED; import static javasabr.mqtt.model.reason.code.UnsubscribeAckReasonCode.SUCCESS; -import static javasabr.mqtt.model.utils.TopicUtils.hasWildcard; -import static javasabr.mqtt.model.utils.TopicUtils.isShared; +import static javasabr.mqtt.model.util.TopicUtils.hasWildcard; +import static javasabr.mqtt.model.util.TopicUtils.isShared; import java.util.function.BiFunction; import javasabr.mqtt.model.ActionResult; @@ -21,7 +21,7 @@ import javasabr.mqtt.model.topic.TopicFilter; import javasabr.mqtt.model.topic.TopicName; import javasabr.mqtt.model.topic.TopicSubscribers; -import javasabr.mqtt.model.utils.TopicUtils; +import javasabr.mqtt.model.util.TopicUtils; import javasabr.mqtt.network.MqttClient; import javasabr.mqtt.network.MqttSession; import javasabr.mqtt.service.SubscriptionService; diff --git a/service/src/main/java/javasabr/mqtt/service/message/handler/MqttInMessageHandler.java b/service/src/main/java/javasabr/mqtt/service/message/handler/MqttInMessageHandler.java index 0f832b66..47d0ef18 100644 --- a/service/src/main/java/javasabr/mqtt/service/message/handler/MqttInMessageHandler.java +++ b/service/src/main/java/javasabr/mqtt/service/message/handler/MqttInMessageHandler.java @@ -1,12 +1,12 @@ package javasabr.mqtt.service.message.handler; import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.MqttPacketType; -import javasabr.mqtt.network.packet.in.MqttReadablePacket; +import javasabr.mqtt.network.message.MqttMessageType; +import javasabr.mqtt.network.message.in.MqttInMessage; public interface MqttInMessageHandler { - MqttPacketType messageType(); + MqttMessageType messageType(); - void processReceived(MqttConnection connection, MqttReadablePacket networkPacket); + void processReceived(MqttConnection connection, MqttInMessage networkPacket); } diff --git a/service/src/main/java/javasabr/mqtt/service/message/handler/impl/AbstractMqttInMessageHandler.java b/service/src/main/java/javasabr/mqtt/service/message/handler/impl/AbstractMqttInMessageHandler.java index 942914f9..b71a5a06 100644 --- a/service/src/main/java/javasabr/mqtt/service/message/handler/impl/AbstractMqttInMessageHandler.java +++ b/service/src/main/java/javasabr/mqtt/service/message/handler/impl/AbstractMqttInMessageHandler.java @@ -2,7 +2,7 @@ import javasabr.mqtt.network.MqttClient; import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.packet.in.MqttReadablePacket; +import javasabr.mqtt.network.message.in.MqttInMessage; import javasabr.mqtt.service.message.handler.MqttInMessageHandler; import lombok.AccessLevel; import lombok.CustomLog; @@ -12,14 +12,14 @@ @CustomLog @RequiredArgsConstructor @FieldDefaults(level = AccessLevel.PROTECTED, makeFinal = true) -public abstract class AbstractMqttInMessageHandler +public abstract class AbstractMqttInMessageHandler implements MqttInMessageHandler { Class expectedClient; Class

expectedNetworkPacket; @Override - public void processReceived(MqttConnection connection, MqttReadablePacket networkPacket) { + public void processReceived(MqttConnection connection, MqttInMessage networkPacket) { MqttClient client = connection.client(); if (!expectedClient.isInstance(client)) { log.warning(client, "Received not expected client:[%s]"::formatted); diff --git a/service/src/main/java/javasabr/mqtt/service/message/handler/impl/ConnectInMqttInMessageHandler.java b/service/src/main/java/javasabr/mqtt/service/message/handler/impl/ConnectInMqttInMessageHandler.java index 91ccae66..60bc6a9b 100644 --- a/service/src/main/java/javasabr/mqtt/service/message/handler/impl/ConnectInMqttInMessageHandler.java +++ b/service/src/main/java/javasabr/mqtt/service/message/handler/impl/ConnectInMqttInMessageHandler.java @@ -20,14 +20,14 @@ import javasabr.mqtt.network.MqttClient; import javasabr.mqtt.network.MqttConnection; import javasabr.mqtt.network.MqttSession; -import javasabr.mqtt.network.client.ExternalMqttClient; -import javasabr.mqtt.network.packet.MqttPacketType; -import javasabr.mqtt.network.packet.in.ConnectInPacket; +import javasabr.mqtt.network.impl.ExternalMqttClient; +import javasabr.mqtt.network.message.MqttMessageType; +import javasabr.mqtt.network.message.in.ConnectMqttInMessage; import javasabr.mqtt.service.AuthenticationService; import javasabr.mqtt.service.ClientIdRegistry; import javasabr.mqtt.service.MessageOutFactoryService; -import javasabr.mqtt.service.SessionService; import javasabr.mqtt.service.SubscriptionService; +import javasabr.mqtt.service.session.MqttSessionService; import javasabr.rlib.common.util.StringUtils; import lombok.AccessLevel; import lombok.CustomLog; @@ -36,21 +36,21 @@ @CustomLog @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) -public class ConnectInMqttInMessageHandler extends AbstractMqttInMessageHandler { +public class ConnectInMqttInMessageHandler extends AbstractMqttInMessageHandler { ClientIdRegistry clientIdRegistry; AuthenticationService authenticationService; - SessionService sessionService; + MqttSessionService sessionService; SubscriptionService subscriptionService; MessageOutFactoryService messageOutFactoryService; public ConnectInMqttInMessageHandler( ClientIdRegistry clientIdRegistry, AuthenticationService authenticationService, - SessionService sessionService, + MqttSessionService sessionService, SubscriptionService subscriptionService, MessageOutFactoryService messageOutFactoryService) { - super(ExternalMqttClient.class, ConnectInPacket.class); + super(ExternalMqttClient.class, ConnectMqttInMessage.class); this.clientIdRegistry = clientIdRegistry; this.authenticationService = authenticationService; this.sessionService = sessionService; @@ -59,15 +59,15 @@ public ConnectInMqttInMessageHandler( } @Override - public MqttPacketType messageType() { - return MqttPacketType.CONNECT; + public MqttMessageType messageType() { + return MqttMessageType.CONNECT; } @Override protected void processReceived( MqttConnection connection, ExternalMqttClient client, - ConnectInPacket networkPacket) { + ConnectMqttInMessage networkPacket) { if (checkPacketException(client, networkPacket)) { return; @@ -86,7 +86,7 @@ private void reject(ExternalMqttClient client, ConnectAckReasonCode connectAckRe .newConnectAck(client, connectAckReasonCode)); } - private Mono registerClient(ExternalMqttClient client, ConnectInPacket networkPacket) { + private Mono registerClient(ExternalMqttClient client, ConnectMqttInMessage networkPacket) { String requestedClientId = networkPacket.clientId(); if (StringUtils.isNotEmpty(requestedClientId)) { @@ -112,7 +112,7 @@ private Mono registerClient(ExternalMqttClient client, ConnectInPacket .map(ifTrue(newClientId, client::clientId))); } - private Mono restoreSession(MqttClient.UnsafeMqttClient client, ConnectInPacket packet) { + private Mono restoreSession(MqttClient.UnsafeMqttClient client, ConnectMqttInMessage packet) { if (packet.cleanStart()) { return sessionService .create(client.clientId()) @@ -127,7 +127,7 @@ private Mono restoreSession(MqttClient.UnsafeMqttClient client, Connect } } - private void resolveClientConnectionConfig(MqttClient.UnsafeMqttClient client, ConnectInPacket packet) { + private void resolveClientConnectionConfig(MqttClient.UnsafeMqttClient client, ConnectMqttInMessage packet) { MqttConnection connection = client.connection(); MqttServerConnectionConfig serverConfig = connection.serverConnectionConfig(); @@ -179,7 +179,7 @@ private void resolveClientConnectionConfig(MqttClient.UnsafeMqttClient client, C private Mono onConnected( MqttClient.UnsafeMqttClient client, - ConnectInPacket packet, + ConnectMqttInMessage packet, MqttSession session, boolean sessionRestored) { @@ -224,7 +224,7 @@ private boolean onSentConnAck(MqttClient.UnsafeMqttClient client, MqttSession se return true; } - private boolean checkPacketException(MqttClient.UnsafeMqttClient client, ConnectInPacket packet) { + private boolean checkPacketException(MqttClient.UnsafeMqttClient client, ConnectMqttInMessage packet) { Exception exception = packet.exception(); if (exception instanceof ConnectionRejectException cre) { client.send(messageOutFactoryService diff --git a/service/src/main/java/javasabr/mqtt/service/message/handler/impl/DisconnectMqttInMessageHandler.java b/service/src/main/java/javasabr/mqtt/service/message/handler/impl/DisconnectMqttInMessageHandler.java index 186eeaa2..5a0142ce 100644 --- a/service/src/main/java/javasabr/mqtt/service/message/handler/impl/DisconnectMqttInMessageHandler.java +++ b/service/src/main/java/javasabr/mqtt/service/message/handler/impl/DisconnectMqttInMessageHandler.java @@ -2,29 +2,29 @@ import javasabr.mqtt.model.reason.code.DisconnectReasonCode; import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.client.ExternalMqttClient; -import javasabr.mqtt.network.packet.MqttPacketType; -import javasabr.mqtt.network.packet.in.DisconnectInPacket; +import javasabr.mqtt.network.impl.ExternalMqttClient; +import javasabr.mqtt.network.message.MqttMessageType; +import javasabr.mqtt.network.message.in.DisconnectMqttInMessage; import lombok.CustomLog; @CustomLog -public class DisconnectMqttInMessageHandler extends AbstractMqttInMessageHandler { +public class DisconnectMqttInMessageHandler extends AbstractMqttInMessageHandler { public DisconnectMqttInMessageHandler() { - super(ExternalMqttClient.class, DisconnectInPacket.class); + super(ExternalMqttClient.class, DisconnectMqttInMessage.class); } @Override - public MqttPacketType messageType() { - return MqttPacketType.DISCONNECT; + public MqttMessageType messageType() { + return MqttMessageType.DISCONNECT; } @Override protected void processReceived( MqttConnection connection, ExternalMqttClient client, - DisconnectInPacket networkPacket) { - DisconnectReasonCode reasonCode = networkPacket.getReasonCode(); + DisconnectMqttInMessage networkPacket) { + DisconnectReasonCode reasonCode = networkPacket.reasonCode(); if (reasonCode == DisconnectReasonCode.NORMAL_DISCONNECTION) { log.info(client.clientId(), "Disconnect client:[%s]"::formatted); } else { diff --git a/service/src/main/java/javasabr/mqtt/service/message/handler/impl/PendingOutResponseMqttInMessageHandler.java b/service/src/main/java/javasabr/mqtt/service/message/handler/impl/PendingOutResponseMqttInMessageHandler.java index eeb3fd6d..505a3b30 100644 --- a/service/src/main/java/javasabr/mqtt/service/message/handler/impl/PendingOutResponseMqttInMessageHandler.java +++ b/service/src/main/java/javasabr/mqtt/service/message/handler/impl/PendingOutResponseMqttInMessageHandler.java @@ -2,11 +2,11 @@ import javasabr.mqtt.network.MqttConnection; import javasabr.mqtt.network.MqttSession; -import javasabr.mqtt.network.client.ExternalMqttClient; -import javasabr.mqtt.network.packet.HasPacketId; -import javasabr.mqtt.network.packet.in.MqttReadablePacket; +import javasabr.mqtt.network.impl.ExternalMqttClient; +import javasabr.mqtt.network.message.HasMessageId; +import javasabr.mqtt.network.message.in.MqttInMessage; -public abstract class PendingOutResponseMqttInMessageHandler

+public abstract class PendingOutResponseMqttInMessageHandler

extends AbstractMqttInMessageHandler { protected PendingOutResponseMqttInMessageHandler(Class

expectedNetworkPacket) { diff --git a/service/src/main/java/javasabr/mqtt/service/message/handler/impl/PublishAckMqttInMessageHandler.java b/service/src/main/java/javasabr/mqtt/service/message/handler/impl/PublishAckMqttInMessageHandler.java index e7c021ed..42718dfe 100644 --- a/service/src/main/java/javasabr/mqtt/service/message/handler/impl/PublishAckMqttInMessageHandler.java +++ b/service/src/main/java/javasabr/mqtt/service/message/handler/impl/PublishAckMqttInMessageHandler.java @@ -1,16 +1,16 @@ package javasabr.mqtt.service.message.handler.impl; -import javasabr.mqtt.network.packet.MqttPacketType; -import javasabr.mqtt.network.packet.in.PublishAckInPacket; +import javasabr.mqtt.network.message.MqttMessageType; +import javasabr.mqtt.network.message.in.PublishAckMqttInMessage; -public class PublishAckMqttInMessageHandler extends PendingOutResponseMqttInMessageHandler { +public class PublishAckMqttInMessageHandler extends PendingOutResponseMqttInMessageHandler { public PublishAckMqttInMessageHandler() { - super(PublishAckInPacket.class); + super(PublishAckMqttInMessage.class); } @Override - public MqttPacketType messageType() { - return MqttPacketType.PUBLISH_ACK; + public MqttMessageType messageType() { + return MqttMessageType.PUBLISH_ACK; } } diff --git a/service/src/main/java/javasabr/mqtt/service/message/handler/impl/PublishCompleteMqttInMessageHandler.java b/service/src/main/java/javasabr/mqtt/service/message/handler/impl/PublishCompleteMqttInMessageHandler.java index 6d807774..c4709854 100644 --- a/service/src/main/java/javasabr/mqtt/service/message/handler/impl/PublishCompleteMqttInMessageHandler.java +++ b/service/src/main/java/javasabr/mqtt/service/message/handler/impl/PublishCompleteMqttInMessageHandler.java @@ -1,17 +1,17 @@ package javasabr.mqtt.service.message.handler.impl; -import javasabr.mqtt.network.packet.MqttPacketType; -import javasabr.mqtt.network.packet.in.PublishCompleteInPacket; +import javasabr.mqtt.network.message.MqttMessageType; +import javasabr.mqtt.network.message.in.PublishCompleteMqttInMessage; public class PublishCompleteMqttInMessageHandler extends - PendingOutResponseMqttInMessageHandler { + PendingOutResponseMqttInMessageHandler { public PublishCompleteMqttInMessageHandler() { - super(PublishCompleteInPacket.class); + super(PublishCompleteMqttInMessage.class); } @Override - public MqttPacketType messageType() { - return MqttPacketType.PUBLISH_COMPLETED; + public MqttMessageType messageType() { + return MqttMessageType.PUBLISH_COMPLETED; } } diff --git a/service/src/main/java/javasabr/mqtt/service/message/handler/impl/PublishMqttInMessageHandler.java b/service/src/main/java/javasabr/mqtt/service/message/handler/impl/PublishMqttInMessageHandler.java index c61bcf1b..d497c5e1 100644 --- a/service/src/main/java/javasabr/mqtt/service/message/handler/impl/PublishMqttInMessageHandler.java +++ b/service/src/main/java/javasabr/mqtt/service/message/handler/impl/PublishMqttInMessageHandler.java @@ -1,20 +1,20 @@ package javasabr.mqtt.service.message.handler.impl; import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.client.ExternalMqttClient; -import javasabr.mqtt.network.packet.MqttPacketType; -import javasabr.mqtt.network.packet.in.PublishInPacket; +import javasabr.mqtt.network.impl.ExternalMqttClient; +import javasabr.mqtt.network.message.MqttMessageType; +import javasabr.mqtt.network.message.in.PublishMqttInMessage; import javasabr.mqtt.service.PublishReceivingService; import lombok.AccessLevel; import lombok.experimental.FieldDefaults; @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) -public class PublishMqttInMessageHandler extends AbstractMqttInMessageHandler { +public class PublishMqttInMessageHandler extends AbstractMqttInMessageHandler { PublishReceivingService publishReceivingService; public PublishMqttInMessageHandler(PublishReceivingService publishReceivingService) { - super(ExternalMqttClient.class, PublishInPacket.class); + super(ExternalMqttClient.class, PublishMqttInMessage.class); this.publishReceivingService = publishReceivingService; } @@ -22,12 +22,12 @@ public PublishMqttInMessageHandler(PublishReceivingService publishReceivingServi protected void processReceived( MqttConnection connection, ExternalMqttClient client, - PublishInPacket networkPacket) { + PublishMqttInMessage networkPacket) { publishReceivingService.processReceivedPublish(client, networkPacket); } @Override - public MqttPacketType messageType() { - return MqttPacketType.PUBLISH; + public MqttMessageType messageType() { + return MqttMessageType.PUBLISH; } } diff --git a/service/src/main/java/javasabr/mqtt/service/message/handler/impl/PublishReceiveMqttInMessageHandler.java b/service/src/main/java/javasabr/mqtt/service/message/handler/impl/PublishReceiveMqttInMessageHandler.java index ee15cc93..39f2ed7e 100644 --- a/service/src/main/java/javasabr/mqtt/service/message/handler/impl/PublishReceiveMqttInMessageHandler.java +++ b/service/src/main/java/javasabr/mqtt/service/message/handler/impl/PublishReceiveMqttInMessageHandler.java @@ -1,17 +1,17 @@ package javasabr.mqtt.service.message.handler.impl; -import javasabr.mqtt.network.packet.MqttPacketType; -import javasabr.mqtt.network.packet.in.PublishReceivedInPacket; +import javasabr.mqtt.network.message.MqttMessageType; +import javasabr.mqtt.network.message.in.PublishReceivedMqttInMessage; public class PublishReceiveMqttInMessageHandler extends - PendingOutResponseMqttInMessageHandler { + PendingOutResponseMqttInMessageHandler { public PublishReceiveMqttInMessageHandler() { - super(PublishReceivedInPacket.class); + super(PublishReceivedMqttInMessage.class); } @Override - public MqttPacketType messageType() { - return MqttPacketType.PUBLISH_RECEIVED; + public MqttMessageType messageType() { + return MqttMessageType.PUBLISH_RECEIVED; } } diff --git a/service/src/main/java/javasabr/mqtt/service/message/handler/impl/PublishReleaseMqttInMessageHandler.java b/service/src/main/java/javasabr/mqtt/service/message/handler/impl/PublishReleaseMqttInMessageHandler.java index 3d1103aa..77ff6195 100644 --- a/service/src/main/java/javasabr/mqtt/service/message/handler/impl/PublishReleaseMqttInMessageHandler.java +++ b/service/src/main/java/javasabr/mqtt/service/message/handler/impl/PublishReleaseMqttInMessageHandler.java @@ -2,27 +2,27 @@ import javasabr.mqtt.network.MqttConnection; import javasabr.mqtt.network.MqttSession; -import javasabr.mqtt.network.client.ExternalMqttClient; -import javasabr.mqtt.network.packet.MqttPacketType; -import javasabr.mqtt.network.packet.in.PublishReleaseInPacket; +import javasabr.mqtt.network.impl.ExternalMqttClient; +import javasabr.mqtt.network.message.MqttMessageType; +import javasabr.mqtt.network.message.in.PublishReleaseMqttInMessage; public class PublishReleaseMqttInMessageHandler - extends AbstractMqttInMessageHandler { + extends AbstractMqttInMessageHandler { public PublishReleaseMqttInMessageHandler() { - super(ExternalMqttClient.class, PublishReleaseInPacket.class); + super(ExternalMqttClient.class, PublishReleaseMqttInMessage.class); } @Override - public MqttPacketType messageType() { - return MqttPacketType.PUBLISH_RELEASED; + public MqttMessageType messageType() { + return MqttMessageType.PUBLISH_RELEASED; } @Override protected void processReceived( MqttConnection connection, ExternalMqttClient client, - PublishReleaseInPacket networkPacket) { + PublishReleaseMqttInMessage networkPacket) { MqttSession session = client.session(); if (session != null) { session.updateInPendingPacket(client, networkPacket); diff --git a/service/src/main/java/javasabr/mqtt/service/message/handler/impl/SubscribeMqttInMessageHandler.java b/service/src/main/java/javasabr/mqtt/service/message/handler/impl/SubscribeMqttInMessageHandler.java index c3329008..af0731e6 100644 --- a/service/src/main/java/javasabr/mqtt/service/message/handler/impl/SubscribeMqttInMessageHandler.java +++ b/service/src/main/java/javasabr/mqtt/service/message/handler/impl/SubscribeMqttInMessageHandler.java @@ -8,10 +8,10 @@ import javasabr.mqtt.model.reason.code.DisconnectReasonCode; import javasabr.mqtt.model.reason.code.SubscribeAckReasonCode; import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.client.ExternalMqttClient; -import javasabr.mqtt.network.packet.MqttPacketType; -import javasabr.mqtt.network.packet.in.SubscribeInPacket; -import javasabr.mqtt.network.packet.out.MqttWritablePacket; +import javasabr.mqtt.network.impl.ExternalMqttClient; +import javasabr.mqtt.network.message.MqttMessageType; +import javasabr.mqtt.network.message.in.SubscribeMqttInMessage; +import javasabr.mqtt.network.message.out.MqttOutMessage; import javasabr.mqtt.service.MessageOutFactoryService; import javasabr.mqtt.service.SubscriptionService; import javasabr.rlib.collections.array.Array; @@ -20,7 +20,7 @@ @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) public class SubscribeMqttInMessageHandler extends - AbstractMqttInMessageHandler { + AbstractMqttInMessageHandler { private final static Set INVALID_ACK_CODE = Set.of( SHARED_SUBSCRIPTIONS_NOT_SUPPORTED, @@ -32,27 +32,27 @@ public class SubscribeMqttInMessageHandler extends public SubscribeMqttInMessageHandler( SubscriptionService subscriptionService, MessageOutFactoryService messageOutFactoryService) { - super(ExternalMqttClient.class, SubscribeInPacket.class); + super(ExternalMqttClient.class, SubscribeMqttInMessage.class); this.subscriptionService = subscriptionService; this.messageOutFactoryService = messageOutFactoryService; } @Override - public MqttPacketType messageType() { - return MqttPacketType.SUBSCRIBE; + public MqttMessageType messageType() { + return MqttMessageType.SUBSCRIBE; } @Override protected void processReceived( MqttConnection connection, ExternalMqttClient client, - SubscribeInPacket networkPacket) { + SubscribeMqttInMessage networkPacket) { Array ackReasonCodes = subscriptionService - .subscribe(client, networkPacket.getTopicFilters()); - MqttWritablePacket subscribeAck = messageOutFactoryService + .subscribe(client, networkPacket.topicFilters()); + MqttOutMessage subscribeAck = messageOutFactoryService .resolveFactory(client) - .newSubscribeAck(networkPacket.getPacketId(), ackReasonCodes); + .newSubscribeAck(networkPacket.messageId(), ackReasonCodes); client.send(subscribeAck); @@ -62,7 +62,7 @@ protected void processReceived( if (anyReason != null) { var disconnectReasonCode = DisconnectReasonCode.of(toUnsignedInt(anyReason.getValue())); - MqttWritablePacket disconnect = messageOutFactoryService + MqttOutMessage disconnect = messageOutFactoryService .resolveFactory(client) .newDisconnect(client, disconnectReasonCode); diff --git a/service/src/main/java/javasabr/mqtt/service/message/handler/impl/UnsubscribeMqttInMessageHandler.java b/service/src/main/java/javasabr/mqtt/service/message/handler/impl/UnsubscribeMqttInMessageHandler.java index c789849a..e8444b41 100644 --- a/service/src/main/java/javasabr/mqtt/service/message/handler/impl/UnsubscribeMqttInMessageHandler.java +++ b/service/src/main/java/javasabr/mqtt/service/message/handler/impl/UnsubscribeMqttInMessageHandler.java @@ -2,9 +2,9 @@ import javasabr.mqtt.model.reason.code.UnsubscribeAckReasonCode; import javasabr.mqtt.network.MqttConnection; -import javasabr.mqtt.network.client.ExternalMqttClient; -import javasabr.mqtt.network.packet.MqttPacketType; -import javasabr.mqtt.network.packet.in.UnsubscribeInPacket; +import javasabr.mqtt.network.impl.ExternalMqttClient; +import javasabr.mqtt.network.message.MqttMessageType; +import javasabr.mqtt.network.message.in.UnsubscribeMqttInMessage; import javasabr.mqtt.service.MessageOutFactoryService; import javasabr.mqtt.service.SubscriptionService; import javasabr.rlib.collections.array.Array; @@ -12,7 +12,7 @@ import lombok.experimental.FieldDefaults; @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) -public class UnsubscribeMqttInMessageHandler extends AbstractMqttInMessageHandler { +public class UnsubscribeMqttInMessageHandler extends AbstractMqttInMessageHandler { SubscriptionService subscriptionService; MessageOutFactoryService messageOutFactoryService; @@ -20,27 +20,27 @@ public class UnsubscribeMqttInMessageHandler extends AbstractMqttInMessageHandle public UnsubscribeMqttInMessageHandler( SubscriptionService subscriptionService, MessageOutFactoryService messageOutFactoryService) { - super(ExternalMqttClient.class, UnsubscribeInPacket.class); + super(ExternalMqttClient.class, UnsubscribeMqttInMessage.class); this.subscriptionService = subscriptionService; this.messageOutFactoryService = messageOutFactoryService; } @Override - public MqttPacketType messageType() { - return MqttPacketType.UNSUBSCRIBE; + public MqttMessageType messageType() { + return MqttMessageType.UNSUBSCRIBE; } @Override protected void processReceived( MqttConnection connection, ExternalMqttClient client, - UnsubscribeInPacket networkPacket) { + UnsubscribeMqttInMessage networkPacket) { Array ackReasonCodes = subscriptionService - .unsubscribe(client, networkPacket.getTopicFilters()); + .unsubscribe(client, networkPacket.topicFilters()); client.send(messageOutFactoryService .resolveFactory(client) - .newUnsubscribeAck(networkPacket.getPacketId(), ackReasonCodes)); + .newUnsubscribeAck(networkPacket.messageId(), ackReasonCodes)); } } diff --git a/service/src/main/java/javasabr/mqtt/service/message/out/factory/Mqtt311MessageOutFactory.java b/service/src/main/java/javasabr/mqtt/service/message/out/factory/Mqtt311MessageOutFactory.java index 0351f9ca..3b9b3189 100644 --- a/service/src/main/java/javasabr/mqtt/service/message/out/factory/Mqtt311MessageOutFactory.java +++ b/service/src/main/java/javasabr/mqtt/service/message/out/factory/Mqtt311MessageOutFactory.java @@ -13,19 +13,19 @@ import javasabr.mqtt.model.reason.code.SubscribeAckReasonCode; import javasabr.mqtt.model.reason.code.UnsubscribeAckReasonCode; import javasabr.mqtt.network.MqttClient; -import javasabr.mqtt.network.packet.out.ConnectAck311OutPacket; -import javasabr.mqtt.network.packet.out.Disconnect311OutPacket; -import javasabr.mqtt.network.packet.out.MqttWritablePacket; -import javasabr.mqtt.network.packet.out.PingRequest311OutPacket; -import javasabr.mqtt.network.packet.out.PingResponse311OutPacket; -import javasabr.mqtt.network.packet.out.Publish311OutPacket; -import javasabr.mqtt.network.packet.out.PublishAck311OutPacket; -import javasabr.mqtt.network.packet.out.PublishComplete311OutPacket; -import javasabr.mqtt.network.packet.out.PublishOutPacket; -import javasabr.mqtt.network.packet.out.PublishReceived311OutPacket; -import javasabr.mqtt.network.packet.out.PublishRelease311OutPacket; -import javasabr.mqtt.network.packet.out.SubscribeAck311OutPacket; -import javasabr.mqtt.network.packet.out.UnsubscribeAck311OutPacket; +import javasabr.mqtt.network.message.out.ConnectAckMqtt311OutMessage; +import javasabr.mqtt.network.message.out.DisconnectMqtt311OutMessage; +import javasabr.mqtt.network.message.out.MqttOutMessage; +import javasabr.mqtt.network.message.out.PingRequestMqtt311OutMessage; +import javasabr.mqtt.network.message.out.PingResponseMqtt311OutMessage; +import javasabr.mqtt.network.message.out.PublishAckMqtt311OutMessage; +import javasabr.mqtt.network.message.out.PublishCompleteMqtt311OutMessage; +import javasabr.mqtt.network.message.out.PublishMqtt311OutMessage; +import javasabr.mqtt.network.message.out.PublishMqttOutMessage; +import javasabr.mqtt.network.message.out.PublishReceivedMqtt311OutMessage; +import javasabr.mqtt.network.message.out.PublishReleaseMqtt311OutMessage; +import javasabr.mqtt.network.message.out.SubscribeAckMqtt311OutMessage; +import javasabr.mqtt.network.message.out.UnsubscribeAckMqtt311OutMessage; import javasabr.rlib.collections.array.Array; public class Mqtt311MessageOutFactory extends MqttMessageOutFactory { @@ -36,7 +36,7 @@ public MqttVersion mqttVersion() { } @Override - public MqttWritablePacket newConnectAck( + public MqttOutMessage newConnectAck( MqttClient client, ConnectAckReasonCode reasonCode, boolean sessionPresent, @@ -50,11 +50,11 @@ public MqttWritablePacket newConnectAck( String authenticationMethod, byte[] authenticationData, Array userProperties) { - return new ConnectAck311OutPacket(reasonCode, sessionPresent); + return new ConnectAckMqtt311OutMessage(reasonCode, sessionPresent); } @Override - public PublishOutPacket newPublish( + public PublishMqttOutMessage newPublish( int packetId, QoS qos, boolean retained, @@ -66,48 +66,48 @@ public PublishOutPacket newPublish( String responseTopic, byte[] correlationData, Array userProperties) { - return new Publish311OutPacket(packetId, qos, retained, duplicate, topicName, payload); + return new PublishMqtt311OutMessage(packetId, qos, retained, duplicate, topicName, payload); } @Override - public MqttWritablePacket newPublishAck( + public MqttOutMessage newPublishAck( int packetId, PublishAckReasonCode reasonCode, String reason, Array userProperties) { - return new PublishAck311OutPacket(packetId); + return new PublishAckMqtt311OutMessage(packetId); } @Override - public MqttWritablePacket newSubscribeAck( + public MqttOutMessage newSubscribeAck( int packetId, Array reasonCodes, String reason, Array userProperties) { - return new SubscribeAck311OutPacket(reasonCodes, packetId); + return new SubscribeAckMqtt311OutMessage(reasonCodes, packetId); } @Override - public MqttWritablePacket newUnsubscribeAck( + public MqttOutMessage newUnsubscribeAck( int packetId, Array reasonCodes, Array userProperties, String reason) { - return new UnsubscribeAck311OutPacket(packetId); + return new UnsubscribeAckMqtt311OutMessage(packetId); } @Override - public MqttWritablePacket newDisconnect( + public MqttOutMessage newDisconnect( MqttClient client, DisconnectReasonCode reasonCode, Array userProperties, String reason, String serverReference) { - return new Disconnect311OutPacket(); + return new DisconnectMqtt311OutMessage(); } @Override - public MqttWritablePacket newAuthenticate( + public MqttOutMessage newAuthenticate( AuthenticateReasonCode reasonCode, String authenticateMethod, byte[] authenticateData, @@ -117,39 +117,39 @@ public MqttWritablePacket newAuthenticate( } @Override - public MqttWritablePacket newPingRequest() { - return new PingRequest311OutPacket(); + public MqttOutMessage newPingRequest() { + return new PingRequestMqtt311OutMessage(); } @Override - public MqttWritablePacket newPingResponse() { - return new PingResponse311OutPacket(); + public MqttOutMessage newPingResponse() { + return new PingResponseMqtt311OutMessage(); } @Override - public MqttWritablePacket newPublishRelease( + public MqttOutMessage newPublishRelease( int packetId, PublishReleaseReasonCode reasonCode, Array userProperties, String reason) { - return new PublishRelease311OutPacket(packetId); + return new PublishReleaseMqtt311OutMessage(packetId); } @Override - public MqttWritablePacket newPublishReceived( + public MqttOutMessage newPublishReceived( int packetId, PublishReceivedReasonCode reasonCode, Array userProperties, String reason) { - return new PublishReceived311OutPacket(packetId); + return new PublishReceivedMqtt311OutMessage(packetId); } @Override - public MqttWritablePacket newPublishCompleted( + public MqttOutMessage newPublishCompleted( int packetId, PublishCompletedReasonCode reasonCode, Array userProperties, String reason) { - return new PublishComplete311OutPacket(packetId); + return new PublishCompleteMqtt311OutMessage(packetId); } } diff --git a/service/src/main/java/javasabr/mqtt/service/message/out/factory/Mqtt5MessageOutFactory.java b/service/src/main/java/javasabr/mqtt/service/message/out/factory/Mqtt5MessageOutFactory.java index 5329f602..0806a15e 100644 --- a/service/src/main/java/javasabr/mqtt/service/message/out/factory/Mqtt5MessageOutFactory.java +++ b/service/src/main/java/javasabr/mqtt/service/message/out/factory/Mqtt5MessageOutFactory.java @@ -14,18 +14,18 @@ import javasabr.mqtt.model.reason.code.SubscribeAckReasonCode; import javasabr.mqtt.model.reason.code.UnsubscribeAckReasonCode; import javasabr.mqtt.network.MqttClient; -import javasabr.mqtt.network.packet.out.Authentication5OutPacket; -import javasabr.mqtt.network.packet.out.ConnectAck5OutPacket; -import javasabr.mqtt.network.packet.out.Disconnect5OutPacket; -import javasabr.mqtt.network.packet.out.MqttWritablePacket; -import javasabr.mqtt.network.packet.out.Publish5OutPacket; -import javasabr.mqtt.network.packet.out.PublishAck5OutPacket; -import javasabr.mqtt.network.packet.out.PublishComplete5OutPacket; -import javasabr.mqtt.network.packet.out.PublishOutPacket; -import javasabr.mqtt.network.packet.out.PublishReceived5OutPacket; -import javasabr.mqtt.network.packet.out.PublishRelease5OutPacket; -import javasabr.mqtt.network.packet.out.SubscribeAck5OutPacket; -import javasabr.mqtt.network.packet.out.UnsubscribeAck5OutPacket; +import javasabr.mqtt.network.message.out.AuthenticationMqtt5OutMessage; +import javasabr.mqtt.network.message.out.ConnectAckMqtt5OutMessage; +import javasabr.mqtt.network.message.out.DisconnectMqtt5OutMessage; +import javasabr.mqtt.network.message.out.MqttOutMessage; +import javasabr.mqtt.network.message.out.PublishAckMqtt5OutMessage; +import javasabr.mqtt.network.message.out.PublishCompleteMqtt5OutMessage; +import javasabr.mqtt.network.message.out.PublishMqtt5OutMessage; +import javasabr.mqtt.network.message.out.PublishMqttOutMessage; +import javasabr.mqtt.network.message.out.PublishReceivedMqtt5OutMessage; +import javasabr.mqtt.network.message.out.PublishReleaseMqtt5OutMessage; +import javasabr.mqtt.network.message.out.SubscribeAckMqtt5OutMessage; +import javasabr.mqtt.network.message.out.UnsubscribeAckMqtt5OutMessage; import javasabr.rlib.collections.array.Array; public class Mqtt5MessageOutFactory extends Mqtt311MessageOutFactory { @@ -36,7 +36,7 @@ public MqttVersion mqttVersion() { } @Override - public MqttWritablePacket newConnectAck( + public MqttOutMessage newConnectAck( MqttClient client, ConnectAckReasonCode reasonCode, boolean sessionPresent, @@ -51,7 +51,7 @@ public MqttWritablePacket newConnectAck( byte[] authenticationData, Array userProperties) { MqttClientConnectionConfig connectionConfig = client.connectionConfig(); - return new ConnectAck5OutPacket( + return new ConnectAckMqtt5OutMessage( connectionConfig, reasonCode, sessionPresent, @@ -69,7 +69,7 @@ public MqttWritablePacket newConnectAck( } @Override - public PublishOutPacket newPublish( + public PublishMqttOutMessage newPublish( int packetId, QoS qos, boolean retained, @@ -81,7 +81,7 @@ public PublishOutPacket newPublish( String responseTopic, byte[] correlationData, Array userProperties) { - return new Publish5OutPacket( + return new PublishMqtt5OutMessage( packetId, qos, retained, @@ -96,41 +96,41 @@ public PublishOutPacket newPublish( } @Override - public MqttWritablePacket newPublishAck( + public MqttOutMessage newPublishAck( int packetId, PublishAckReasonCode reasonCode, String reason, Array userProperties) { - return new PublishAck5OutPacket(packetId, reasonCode, userProperties, reason); + return new PublishAckMqtt5OutMessage(packetId, reasonCode, userProperties, reason); } @Override - public MqttWritablePacket newSubscribeAck( + public MqttOutMessage newSubscribeAck( int packetId, Array reasonCodes, String reason, Array userProperties) { - return new SubscribeAck5OutPacket(packetId, reasonCodes, userProperties, reason); + return new SubscribeAckMqtt5OutMessage(packetId, reasonCodes, userProperties, reason); } @Override - public MqttWritablePacket newUnsubscribeAck( + public MqttOutMessage newUnsubscribeAck( int packetId, Array reasonCodes, Array userProperties, String reason) { - return new UnsubscribeAck5OutPacket(packetId, reasonCodes, userProperties, reason); + return new UnsubscribeAckMqtt5OutMessage(packetId, reasonCodes, userProperties, reason); } @Override - public MqttWritablePacket newDisconnect( + public MqttOutMessage newDisconnect( MqttClient client, DisconnectReasonCode reasonCode, Array userProperties, String reason, String serverReference) { MqttClientConnectionConfig connectionConfig = client.connectionConfig(); - return new Disconnect5OutPacket( + return new DisconnectMqtt5OutMessage( reasonCode, userProperties, reason, @@ -139,39 +139,39 @@ public MqttWritablePacket newDisconnect( } @Override - public MqttWritablePacket newAuthenticate( + public MqttOutMessage newAuthenticate( AuthenticateReasonCode reasonCode, String authenticateMethod, byte[] authenticateData, Array userProperties, String reason) { - return new Authentication5OutPacket(userProperties, reasonCode, reason, authenticateMethod, authenticateData); + return new AuthenticationMqtt5OutMessage(userProperties, reasonCode, reason, authenticateMethod, authenticateData); } @Override - public MqttWritablePacket newPublishRelease( + public MqttOutMessage newPublishRelease( int packetId, PublishReleaseReasonCode reasonCode, Array userProperties, String reason) { - return new PublishRelease5OutPacket(packetId, reasonCode, userProperties, reason); + return new PublishReleaseMqtt5OutMessage(packetId, reasonCode, userProperties, reason); } @Override - public MqttWritablePacket newPublishReceived( + public MqttOutMessage newPublishReceived( int packetId, PublishReceivedReasonCode reasonCode, Array userProperties, String reason) { - return new PublishReceived5OutPacket(packetId, reasonCode, userProperties, reason); + return new PublishReceivedMqtt5OutMessage(packetId, reasonCode, userProperties, reason); } @Override - public MqttWritablePacket newPublishCompleted( + public MqttOutMessage newPublishCompleted( int packetId, PublishCompletedReasonCode reasonCode, Array userProperties, String reason) { - return new PublishComplete5OutPacket(packetId, reasonCode, userProperties, reason); + return new PublishCompleteMqtt5OutMessage(packetId, reasonCode, userProperties, reason); } } diff --git a/service/src/main/java/javasabr/mqtt/service/message/out/factory/MqttMessageOutFactory.java b/service/src/main/java/javasabr/mqtt/service/message/out/factory/MqttMessageOutFactory.java index e5f79952..e1711731 100644 --- a/service/src/main/java/javasabr/mqtt/service/message/out/factory/MqttMessageOutFactory.java +++ b/service/src/main/java/javasabr/mqtt/service/message/out/factory/MqttMessageOutFactory.java @@ -14,8 +14,8 @@ import javasabr.mqtt.model.reason.code.SubscribeAckReasonCode; import javasabr.mqtt.model.reason.code.UnsubscribeAckReasonCode; import javasabr.mqtt.network.MqttClient; -import javasabr.mqtt.network.packet.out.MqttWritablePacket; -import javasabr.mqtt.network.packet.out.PublishOutPacket; +import javasabr.mqtt.network.message.out.MqttOutMessage; +import javasabr.mqtt.network.message.out.PublishMqttOutMessage; import javasabr.rlib.collections.array.Array; import javasabr.rlib.collections.array.MutableArray; import javasabr.rlib.common.util.ArrayUtils; @@ -25,7 +25,7 @@ public abstract class MqttMessageOutFactory { public abstract MqttVersion mqttVersion(); - public abstract MqttWritablePacket newConnectAck( + public abstract MqttOutMessage newConnectAck( MqttClient client, ConnectAckReasonCode reasonCode, boolean sessionPresent, @@ -40,7 +40,7 @@ public abstract MqttWritablePacket newConnectAck( byte[] authenticationData, Array userProperties); - public MqttWritablePacket newConnectAck( + public MqttOutMessage newConnectAck( MqttClient client, ConnectAckReasonCode reasonCode, boolean sessionPresent, @@ -64,7 +64,7 @@ public MqttWritablePacket newConnectAck( MutableArray.ofType(StringPair.class)); } - public MqttWritablePacket newConnectAck(MqttClient client, ConnectAckReasonCode reasonCode) { + public MqttOutMessage newConnectAck(MqttClient client, ConnectAckReasonCode reasonCode) { MqttClientConnectionConfig connectionConfig = client.connectionConfig(); return newConnectAck( client, @@ -82,7 +82,7 @@ public MqttWritablePacket newConnectAck(MqttClient client, ConnectAckReasonCode MutableArray.ofType(StringPair.class)); } - public PublishOutPacket newPublish( + public PublishMqttOutMessage newPublish( int packetId, QoS qos, boolean retained, @@ -103,7 +103,7 @@ public PublishOutPacket newPublish( MutableArray.ofType(StringPair.class)); } - public abstract PublishOutPacket newPublish( + public abstract PublishMqttOutMessage newPublish( int packetId, QoS qos, boolean retained, @@ -116,44 +116,44 @@ public abstract PublishOutPacket newPublish( byte[] correlationData, Array userProperties); - public abstract MqttWritablePacket newPublishAck( + public abstract MqttOutMessage newPublishAck( int packetId, PublishAckReasonCode reasonCode, String reason, Array userProperties); - public MqttWritablePacket newPublishAck(int packetId, PublishAckReasonCode reasonCode) { + public MqttOutMessage newPublishAck(int packetId, PublishAckReasonCode reasonCode) { return newPublishAck(packetId, reasonCode, StringUtils.EMPTY, Array.empty(StringPair.class)); } - public abstract MqttWritablePacket newSubscribeAck( + public abstract MqttOutMessage newSubscribeAck( int packetId, Array reasonCodes, String reason, Array userProperties); - public MqttWritablePacket newSubscribeAck(int packetId, Array reasonCodes) { + public MqttOutMessage newSubscribeAck(int packetId, Array reasonCodes) { return newSubscribeAck(packetId, reasonCodes, StringUtils.EMPTY, Array.empty(StringPair.class)); } - public abstract MqttWritablePacket newUnsubscribeAck( + public abstract MqttOutMessage newUnsubscribeAck( int packetId, Array reasonCodes, Array userProperties, String reason); - public MqttWritablePacket newUnsubscribeAck(int packetId, Array reasonCodes) { + public MqttOutMessage newUnsubscribeAck(int packetId, Array reasonCodes) { return newUnsubscribeAck(packetId, reasonCodes, Array.empty(StringPair.class), StringUtils.EMPTY); } - public abstract MqttWritablePacket newDisconnect( + public abstract MqttOutMessage newDisconnect( MqttClient client, DisconnectReasonCode reasonCode, Array userProperties, String reason, String serverReference); - public MqttWritablePacket newDisconnect(MqttClient client, DisconnectReasonCode reasonCode) { + public MqttOutMessage newDisconnect(MqttClient client, DisconnectReasonCode reasonCode) { return newDisconnect( client, reasonCode, @@ -162,14 +162,14 @@ public MqttWritablePacket newDisconnect(MqttClient client, DisconnectReasonCode StringUtils.EMPTY); } - public abstract MqttWritablePacket newAuthenticate( + public abstract MqttOutMessage newAuthenticate( AuthenticateReasonCode reasonCode, String authenticateMethod, byte[] authenticateData, Array userProperties, String reason); - public MqttWritablePacket newAuthenticate( + public MqttOutMessage newAuthenticate( AuthenticateReasonCode reasonCode, String authenticateMethod, byte[] authenticateData) { @@ -181,37 +181,37 @@ public MqttWritablePacket newAuthenticate( StringUtils.EMPTY); } - public abstract MqttWritablePacket newPingRequest(); + public abstract MqttOutMessage newPingRequest(); - public abstract MqttWritablePacket newPingResponse(); + public abstract MqttOutMessage newPingResponse(); - public abstract MqttWritablePacket newPublishRelease( + public abstract MqttOutMessage newPublishRelease( int packetId, PublishReleaseReasonCode reasonCode, Array userProperties, String reason); - public MqttWritablePacket newPublishRelease(int packetId, PublishReleaseReasonCode reasonCode) { + public MqttOutMessage newPublishRelease(int packetId, PublishReleaseReasonCode reasonCode) { return newPublishRelease(packetId, reasonCode, Array.empty(StringPair.class), StringUtils.EMPTY); } - public abstract MqttWritablePacket newPublishReceived( + public abstract MqttOutMessage newPublishReceived( int packetId, PublishReceivedReasonCode reasonCode, Array userProperties, String reason); - public MqttWritablePacket newPublishReceived(int packetId, PublishReceivedReasonCode reasonCode) { + public MqttOutMessage newPublishReceived(int packetId, PublishReceivedReasonCode reasonCode) { return newPublishReceived(packetId, reasonCode, Array.empty(StringPair.class), StringUtils.EMPTY); } - public abstract MqttWritablePacket newPublishCompleted( + public abstract MqttOutMessage newPublishCompleted( int packetId, PublishCompletedReasonCode reasonCode, Array userProperties, String reason); - public MqttWritablePacket newPublishCompleted(int packetId, PublishCompletedReasonCode reasonCode) { + public MqttOutMessage newPublishCompleted(int packetId, PublishCompletedReasonCode reasonCode) { return newPublishCompleted(packetId, reasonCode, Array.empty(StringPair.class), StringUtils.EMPTY); } } diff --git a/service/src/main/java/javasabr/mqtt/service/publish/handler/MqttPublishInMessageHandler.java b/service/src/main/java/javasabr/mqtt/service/publish/handler/MqttPublishInMessageHandler.java index 24f76c29..44a1195f 100644 --- a/service/src/main/java/javasabr/mqtt/service/publish/handler/MqttPublishInMessageHandler.java +++ b/service/src/main/java/javasabr/mqtt/service/publish/handler/MqttPublishInMessageHandler.java @@ -2,11 +2,11 @@ import javasabr.mqtt.model.QoS; import javasabr.mqtt.network.MqttClient; -import javasabr.mqtt.network.packet.in.PublishInPacket; +import javasabr.mqtt.network.message.in.PublishMqttInMessage; public interface MqttPublishInMessageHandler { QoS qos(); - void handle(MqttClient client, PublishInPacket packet); + void handle(MqttClient client, PublishMqttInMessage packet); } diff --git a/service/src/main/java/javasabr/mqtt/service/publish/handler/MqttPublishOutMessageHandler.java b/service/src/main/java/javasabr/mqtt/service/publish/handler/MqttPublishOutMessageHandler.java index c6c00508..e0258d09 100644 --- a/service/src/main/java/javasabr/mqtt/service/publish/handler/MqttPublishOutMessageHandler.java +++ b/service/src/main/java/javasabr/mqtt/service/publish/handler/MqttPublishOutMessageHandler.java @@ -2,11 +2,11 @@ import javasabr.mqtt.model.QoS; import javasabr.mqtt.model.subscriber.SingleSubscriber; -import javasabr.mqtt.network.packet.in.PublishInPacket; +import javasabr.mqtt.network.message.in.PublishMqttInMessage; public interface MqttPublishOutMessageHandler { QoS qos(); - PublishHandlingResult handle(PublishInPacket packet, SingleSubscriber subscriber); + PublishHandlingResult handle(PublishMqttInMessage packet, SingleSubscriber subscriber); } diff --git a/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/AbstractMqttPublishInMessageHandler.java b/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/AbstractMqttPublishInMessageHandler.java index dfb4914d..6ca8ad56 100644 --- a/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/AbstractMqttPublishInMessageHandler.java +++ b/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/AbstractMqttPublishInMessageHandler.java @@ -3,7 +3,7 @@ import javasabr.mqtt.model.subscriber.SingleSubscriber; import javasabr.mqtt.model.topic.TopicName; import javasabr.mqtt.network.MqttClient; -import javasabr.mqtt.network.packet.in.PublishInPacket; +import javasabr.mqtt.network.message.in.PublishMqttInMessage; import javasabr.mqtt.service.PublishDeliveringService; import javasabr.mqtt.service.SubscriptionService; import javasabr.mqtt.service.publish.handler.MqttPublishInMessageHandler; @@ -25,7 +25,7 @@ public abstract class AbstractMqttPublishInMessageHandler PublishDeliveringService publishDeliveringService; @Override - public void handle(MqttClient client, PublishInPacket packet) { + public void handle(MqttClient client, PublishMqttInMessage packet) { if (!expectedClient.isInstance(client)) { log.warning(client, "Not expected client:[%s]"::formatted); return; @@ -33,23 +33,23 @@ public void handle(MqttClient client, PublishInPacket packet) { handleImpl(expectedClient.cast(client), packet); } - protected void handleImpl(C client, PublishInPacket packet) { - TopicName topicName = packet.getTopicName(); + protected void handleImpl(C client, PublishMqttInMessage packet) { + TopicName topicName = packet.topicName(); if (!subscriptionService.isValid(topicName)) { - handleInvalidTopic(client, packet.getPacketId(), topicName); + handleInvalidTopic(client, packet.messageId(), topicName); return; } Array subscribers = subscriptionService.findSubscribers(topicName); if (subscribers.isEmpty()) { - handleEmptySubscriptions(client, packet.getPacketId(), topicName); + handleEmptySubscriptions(client, packet.messageId(), topicName); return; } for (SingleSubscriber subscriber : subscribers) { PublishHandlingResult checkResult = checkSubscriber(client, packet, subscriber); if (checkResult.error()) { - handleError(client, packet.getPacketId(), checkResult); + handleError(client, packet.messageId(), checkResult); return; } } @@ -66,7 +66,7 @@ protected void handleImpl(C client, PublishInPacket packet) { } if (errorResult != null) { - handleError(client, packet.getPacketId(), errorResult); + handleError(client, packet.messageId(), errorResult); } else { handleSuccessfulResult(client, packet, count); } @@ -78,16 +78,16 @@ protected void handleEmptySubscriptions(C client, int messageId, TopicName topic protected void handleError(C client, int messageId, PublishHandlingResult handlingResult) {} - protected void handleSuccessfulResult(C client, PublishInPacket packet, int subscribers) {} + protected void handleSuccessfulResult(C client, PublishMqttInMessage packet, int subscribers) {} protected PublishHandlingResult checkSubscriber( C client, - PublishInPacket packet, + PublishMqttInMessage packet, SingleSubscriber subscriber) { return PublishHandlingResult.SUCCESS; } - protected PublishHandlingResult startDelivering(C client, PublishInPacket packet, SingleSubscriber subscriber) { + protected PublishHandlingResult startDelivering(C client, PublishMqttInMessage packet, SingleSubscriber subscriber) { return publishDeliveringService.startDelivering(packet, subscriber); } } diff --git a/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/AbstractMqttPublishOutMessageHandler.java b/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/AbstractMqttPublishOutMessageHandler.java index 6de94050..6c0fcec1 100644 --- a/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/AbstractMqttPublishOutMessageHandler.java +++ b/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/AbstractMqttPublishOutMessageHandler.java @@ -3,8 +3,8 @@ import javasabr.mqtt.model.MqttProperties; import javasabr.mqtt.model.subscriber.SingleSubscriber; import javasabr.mqtt.network.MqttClient; -import javasabr.mqtt.network.packet.in.PublishInPacket; -import javasabr.mqtt.network.packet.out.PublishOutPacket; +import javasabr.mqtt.network.message.in.PublishMqttInMessage; +import javasabr.mqtt.network.message.out.PublishMqttOutMessage; import javasabr.mqtt.service.MessageOutFactoryService; import javasabr.mqtt.service.SubscriptionService; import javasabr.mqtt.service.publish.handler.MqttPublishOutMessageHandler; @@ -25,7 +25,7 @@ public abstract class AbstractMqttPublishOutMessageHandler MessageOutFactoryService messageOutFactoryService; @Override - public PublishHandlingResult handle(PublishInPacket packet, SingleSubscriber subscriber) { + public PublishHandlingResult handle(PublishMqttInMessage packet, SingleSubscriber subscriber) { MqttClient mqttClient = subscriptionService.resolveClient(subscriber); if (!expectedClient.isInstance(mqttClient)) { log.warning(mqttClient, "Accepted not expected client:[%s]"::formatted); @@ -34,28 +34,28 @@ public PublishHandlingResult handle(PublishInPacket packet, SingleSubscriber sub return handleImpl(packet, expectedClient.cast(mqttClient)); } - protected abstract PublishHandlingResult handleImpl(PublishInPacket packet, C client) ; + protected abstract PublishHandlingResult handleImpl(PublishMqttInMessage packet, C client) ; protected void startDelivering( MqttClient client, - PublishInPacket packet, + PublishMqttInMessage packet, int messageId, boolean duplicate) { - PublishOutPacket publish = messageOutFactoryService + PublishMqttOutMessage publish = messageOutFactoryService .resolveFactory(client) .newPublish( messageId, qos(), - packet.isRetained(), + packet.retained(), duplicate, packet - .getTopicName() + .topicName() .toString(), MqttProperties.TOPIC_ALIAS_NOT_SET, - packet.getPayload(), - packet.isPayloadFormatIndicator(), - packet.getResponseTopic(), - packet.getCorrelationData(), + packet.payload(), + packet.payloadFormatIndicator(), + packet.responseTopic(), + packet.correlationData(), packet.userProperties()); client.send(publish); } diff --git a/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/PersistedMqttPublishOutMessageHandler.java b/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/PersistedMqttPublishOutMessageHandler.java index e596bdf7..633cbaae 100644 --- a/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/PersistedMqttPublishOutMessageHandler.java +++ b/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/PersistedMqttPublishOutMessageHandler.java @@ -3,9 +3,9 @@ import javasabr.mqtt.network.MqttClient; import javasabr.mqtt.network.MqttSession; import javasabr.mqtt.network.MqttSession.PendingMessageHandler; -import javasabr.mqtt.network.client.ExternalMqttClient; -import javasabr.mqtt.network.packet.HasPacketId; -import javasabr.mqtt.network.packet.in.PublishInPacket; +import javasabr.mqtt.network.impl.ExternalMqttClient; +import javasabr.mqtt.network.message.HasMessageId; +import javasabr.mqtt.network.message.in.PublishMqttInMessage; import javasabr.mqtt.service.MessageOutFactoryService; import javasabr.mqtt.service.SubscriptionService; import javasabr.mqtt.service.publish.handler.PublishHandlingResult; @@ -23,18 +23,18 @@ protected PersistedMqttPublishOutMessageHandler( super(ExternalMqttClient.class, subscriptionService, messageOutFactoryService); this.pendingMessageHandler = new PendingMessageHandler() { @Override - public boolean handleResponse(MqttClient client, HasPacketId response) { + public boolean handleResponse(MqttClient client, HasMessageId response) { return handleReceivedResponse(client, response); } @Override - public void resend(MqttClient client, PublishInPacket packet, int packetId) { + public void resend(MqttClient client, PublishMqttInMessage packet, int packetId) { tryToDeliverAgain(client, packet, packetId); } }; } @Override - protected PublishHandlingResult handleImpl(PublishInPacket packet, ExternalMqttClient client) { + protected PublishHandlingResult handleImpl(PublishMqttInMessage packet, ExternalMqttClient client) { MqttSession session = client.session(); if (session == null) { @@ -51,11 +51,11 @@ protected PublishHandlingResult handleImpl(PublishInPacket packet, ExternalMqttC return PublishHandlingResult.SUCCESS; } - protected boolean handleReceivedResponse(MqttClient client, HasPacketId response) { + protected boolean handleReceivedResponse(MqttClient client, HasMessageId response) { return false; } - protected void tryToDeliverAgain(MqttClient client, PublishInPacket packet, int messageId) { + protected void tryToDeliverAgain(MqttClient client, PublishMqttInMessage packet, int messageId) { startDelivering(client, packet, messageId, true); } } diff --git a/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/Qos0MqttPublishInMessageHandler.java b/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/Qos0MqttPublishInMessageHandler.java index 5fc10f21..3870356d 100644 --- a/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/Qos0MqttPublishInMessageHandler.java +++ b/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/Qos0MqttPublishInMessageHandler.java @@ -1,7 +1,7 @@ package javasabr.mqtt.service.publish.handler.impl; import javasabr.mqtt.model.QoS; -import javasabr.mqtt.network.client.ExternalMqttClient; +import javasabr.mqtt.network.impl.ExternalMqttClient; import javasabr.mqtt.service.PublishDeliveringService; import javasabr.mqtt.service.SubscriptionService; diff --git a/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/Qos0MqttPublishOutMessageHandler.java b/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/Qos0MqttPublishOutMessageHandler.java index 39a6aad7..592f24cf 100644 --- a/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/Qos0MqttPublishOutMessageHandler.java +++ b/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/Qos0MqttPublishOutMessageHandler.java @@ -1,8 +1,8 @@ package javasabr.mqtt.service.publish.handler.impl; import javasabr.mqtt.model.QoS; -import javasabr.mqtt.network.client.ExternalMqttClient; -import javasabr.mqtt.network.packet.in.PublishInPacket; +import javasabr.mqtt.network.impl.ExternalMqttClient; +import javasabr.mqtt.network.message.in.PublishMqttInMessage; import javasabr.mqtt.service.MessageOutFactoryService; import javasabr.mqtt.service.SubscriptionService; import javasabr.mqtt.service.publish.handler.PublishHandlingResult; @@ -21,8 +21,8 @@ public QoS qos() { } @Override - protected PublishHandlingResult handleImpl(PublishInPacket packet, ExternalMqttClient client) { - startDelivering(client, packet, packet.getPacketId(), false); + protected PublishHandlingResult handleImpl(PublishMqttInMessage packet, ExternalMqttClient client) { + startDelivering(client, packet, packet.messageId(), false); return PublishHandlingResult.SUCCESS; } } diff --git a/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/Qos1MqttPublishInMessageHandler.java b/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/Qos1MqttPublishInMessageHandler.java index c7b0218e..df1ddb1f 100644 --- a/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/Qos1MqttPublishInMessageHandler.java +++ b/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/Qos1MqttPublishInMessageHandler.java @@ -3,8 +3,8 @@ import javasabr.mqtt.model.QoS; import javasabr.mqtt.model.reason.code.PublishAckReasonCode; import javasabr.mqtt.model.topic.TopicName; -import javasabr.mqtt.network.client.ExternalMqttClient; -import javasabr.mqtt.network.packet.in.PublishInPacket; +import javasabr.mqtt.network.impl.ExternalMqttClient; +import javasabr.mqtt.network.message.in.PublishMqttInMessage; import javasabr.mqtt.service.MessageOutFactoryService; import javasabr.mqtt.service.PublishDeliveringService; import javasabr.mqtt.service.SubscriptionService; @@ -55,10 +55,10 @@ protected void handleError(ExternalMqttClient client, int messageId, PublishHand } @Override - protected void handleSuccessfulResult(ExternalMqttClient client, PublishInPacket packet, int subscribers) { + protected void handleSuccessfulResult(ExternalMqttClient client, PublishMqttInMessage packet, int subscribers) { super.handleSuccessfulResult(client, packet, subscribers); client.send(messageOutFactoryService .resolveFactory(client) - .newPublishAck(packet.getPacketId(), PublishAckReasonCode.SUCCESS)); + .newPublishAck(packet.messageId(), PublishAckReasonCode.SUCCESS)); } } diff --git a/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/Qos1MqttPublishOutMessageHandler.java b/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/Qos1MqttPublishOutMessageHandler.java index 332d3dc0..53cd94ef 100644 --- a/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/Qos1MqttPublishOutMessageHandler.java +++ b/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/Qos1MqttPublishOutMessageHandler.java @@ -2,8 +2,8 @@ import javasabr.mqtt.model.QoS; import javasabr.mqtt.network.MqttClient; -import javasabr.mqtt.network.packet.HasPacketId; -import javasabr.mqtt.network.packet.in.PublishAckInPacket; +import javasabr.mqtt.network.message.HasMessageId; +import javasabr.mqtt.network.message.in.PublishAckMqttInMessage; import javasabr.mqtt.service.MessageOutFactoryService; import javasabr.mqtt.service.SubscriptionService; @@ -21,8 +21,8 @@ public QoS qos() { } @Override - protected boolean handleReceivedResponse(MqttClient client, HasPacketId response) { - if (!(response instanceof PublishAckInPacket)) { + protected boolean handleReceivedResponse(MqttClient client, HasMessageId response) { + if (!(response instanceof PublishAckMqttInMessage)) { throw new IllegalStateException("Unexpected response: " + response); } // just return 'true' to remove pending packet from session diff --git a/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/Qos2MqttPublishInMessageHandler.java b/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/Qos2MqttPublishInMessageHandler.java index 301a8d75..bc92eff2 100644 --- a/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/Qos2MqttPublishInMessageHandler.java +++ b/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/Qos2MqttPublishInMessageHandler.java @@ -7,10 +7,10 @@ import javasabr.mqtt.network.MqttClient; import javasabr.mqtt.network.MqttSession; import javasabr.mqtt.network.MqttSession.PendingMessageHandler; -import javasabr.mqtt.network.client.ExternalMqttClient; -import javasabr.mqtt.network.packet.HasPacketId; -import javasabr.mqtt.network.packet.in.PublishInPacket; -import javasabr.mqtt.network.packet.in.PublishReleaseInPacket; +import javasabr.mqtt.network.impl.ExternalMqttClient; +import javasabr.mqtt.network.message.HasMessageId; +import javasabr.mqtt.network.message.in.PublishMqttInMessage; +import javasabr.mqtt.network.message.in.PublishReleaseMqttInMessage; import javasabr.mqtt.service.MessageOutFactoryService; import javasabr.mqtt.service.PublishDeliveringService; import javasabr.mqtt.service.SubscriptionService; @@ -41,15 +41,15 @@ public QoS qos() { } @Override - protected void handleImpl(ExternalMqttClient client, PublishInPacket packet) { + protected void handleImpl(ExternalMqttClient client, PublishMqttInMessage packet) { MqttSession session = client.session(); if (session == null) { return; } // if this packet is re-try from client - if (packet.isDuplicate()) { + if (packet.duplicate()) { // if this packet was accepted before then we can skip it - if (session.hasInPending(packet.getPacketId())) { + if (session.hasInPending(packet.messageId())) { return; } } @@ -81,26 +81,26 @@ protected void handleError(ExternalMqttClient client, int messageId, PublishHand } @Override - protected void handleSuccessfulResult(ExternalMqttClient client, PublishInPacket packet, int subscribers) { + protected void handleSuccessfulResult(ExternalMqttClient client, PublishMqttInMessage packet, int subscribers) { super.handleSuccessfulResult(client, packet, subscribers); MqttSession session = client.session(); if (session == null) { return; } - session.registerInPublish(packet, pendingMessageHandler, packet.getPacketId()); + session.registerInPublish(packet, pendingMessageHandler, packet.messageId()); client.send(messageOutFactoryService .resolveFactory(client) - .newPublishReceived(packet.getPacketId(), PublishReceivedReasonCode.SUCCESS)); + .newPublishReceived(packet.messageId(), PublishReceivedReasonCode.SUCCESS)); } - private boolean processPublishRelease(MqttClient client, HasPacketId response) { - if (!(response instanceof PublishReleaseInPacket)) { + private boolean processPublishRelease(MqttClient client, HasMessageId response) { + if (!(response instanceof PublishReleaseMqttInMessage)) { throw new IllegalStateException("Unexpected response " + response); } client.send(messageOutFactoryService .resolveFactory(client) - .newPublishCompleted(response.packetId(), PublishCompletedReasonCode.SUCCESS)); + .newPublishCompleted(response.messageId(), PublishCompletedReasonCode.SUCCESS)); return true; } } diff --git a/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/Qos2MqttPublishOutMessageHandler.java b/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/Qos2MqttPublishOutMessageHandler.java index 86ff975a..40afec99 100644 --- a/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/Qos2MqttPublishOutMessageHandler.java +++ b/service/src/main/java/javasabr/mqtt/service/publish/handler/impl/Qos2MqttPublishOutMessageHandler.java @@ -4,9 +4,9 @@ import javasabr.mqtt.model.QoS; import javasabr.mqtt.network.MqttClient; -import javasabr.mqtt.network.packet.HasPacketId; -import javasabr.mqtt.network.packet.in.PublishCompleteInPacket; -import javasabr.mqtt.network.packet.in.PublishReceivedInPacket; +import javasabr.mqtt.network.message.HasMessageId; +import javasabr.mqtt.network.message.in.PublishCompleteMqttInMessage; +import javasabr.mqtt.network.message.in.PublishReceivedMqttInMessage; import javasabr.mqtt.service.MessageOutFactoryService; import javasabr.mqtt.service.SubscriptionService; @@ -24,13 +24,13 @@ public QoS qos() { } @Override - protected boolean handleReceivedResponse(MqttClient client, HasPacketId response) { - if (response instanceof PublishReceivedInPacket) { + protected boolean handleReceivedResponse(MqttClient client, HasMessageId response) { + if (response instanceof PublishReceivedMqttInMessage) { client.send(messageOutFactoryService .resolveFactory(client) - .newPublishRelease(response.packetId(), SUCCESS)); + .newPublishRelease(response.messageId(), SUCCESS)); return false; - } else if (response instanceof PublishCompleteInPacket) { + } else if (response instanceof PublishCompleteMqttInMessage) { return true; } else { throw new IllegalStateException("Unexpected response: " + response); diff --git a/service/src/main/java/javasabr/mqtt/service/SessionService.java b/service/src/main/java/javasabr/mqtt/service/session/MqttSessionService.java similarity index 77% rename from service/src/main/java/javasabr/mqtt/service/SessionService.java rename to service/src/main/java/javasabr/mqtt/service/session/MqttSessionService.java index 23cb00d9..94b1f014 100644 --- a/service/src/main/java/javasabr/mqtt/service/SessionService.java +++ b/service/src/main/java/javasabr/mqtt/service/session/MqttSessionService.java @@ -1,9 +1,9 @@ -package javasabr.mqtt.service; +package javasabr.mqtt.service.session; import javasabr.mqtt.network.MqttSession; import reactor.core.publisher.Mono; -public interface SessionService { +public interface MqttSessionService { Mono restore(String clientId); diff --git a/network/src/main/java/javasabr/mqtt/network/impl/DefaultMqttSession.java b/service/src/main/java/javasabr/mqtt/service/session/impl/InMemoryMqttSession.java similarity index 88% rename from network/src/main/java/javasabr/mqtt/network/impl/DefaultMqttSession.java rename to service/src/main/java/javasabr/mqtt/service/session/impl/InMemoryMqttSession.java index e7fd08d0..8b1c0be0 100644 --- a/network/src/main/java/javasabr/mqtt/network/impl/DefaultMqttSession.java +++ b/service/src/main/java/javasabr/mqtt/service/session/impl/InMemoryMqttSession.java @@ -1,4 +1,4 @@ -package javasabr.mqtt.network.impl; +package javasabr.mqtt.service.session.impl; import java.util.Collection; import java.util.concurrent.atomic.AtomicInteger; @@ -7,8 +7,8 @@ import javasabr.mqtt.model.topic.TopicFilter; import javasabr.mqtt.network.MqttClient; import javasabr.mqtt.network.MqttSession.UnsafeMqttSession; -import javasabr.mqtt.network.packet.HasPacketId; -import javasabr.mqtt.network.packet.in.PublishInPacket; +import javasabr.mqtt.network.message.HasMessageId; +import javasabr.mqtt.network.message.in.PublishMqttInMessage; import javasabr.rlib.collections.array.ArrayFactory; import javasabr.rlib.collections.array.LockableArray; import javasabr.rlib.functions.TriConsumer; @@ -24,18 +24,18 @@ @ToString(of = "clientId") @EqualsAndHashCode(of = "clientId") @Accessors(fluent = true, chain = false) -public class DefaultMqttSession implements UnsafeMqttSession { +public class InMemoryMqttSession implements UnsafeMqttSession { @Getter @AllArgsConstructor private static class PendingPublish { - private final PublishInPacket publish; + private final PublishMqttInMessage publish; private final PendingMessageHandler handler; private final int packetId; } private static void registerPublish( - PublishInPacket publish, + PublishMqttInMessage publish, PendingMessageHandler handler, int packetId, LockableArray pendingPublishes) { @@ -47,11 +47,11 @@ private static void registerPublish( private static void updatePendingPacket( MqttClient client, - HasPacketId response, + HasMessageId response, LockableArray pendingPublishes, String clientId) { - int packetId = response.packetId(); + int packetId = response.messageId(); PendingPublish pendingPublish; long stamp = pendingPublishes.readLock(); @@ -87,7 +87,7 @@ private static void updatePendingPacket( @Setter private volatile long expirationTime = -1; - public DefaultMqttSession(String clientId) { + public InMemoryMqttSession(String clientId) { this.clientId = clientId; this.pendingOutPublishes = ArrayFactory.stampedLockBasedArray(PendingPublish.class); this.pendingInPublishes = ArrayFactory.stampedLockBasedArray(PendingPublish.class); @@ -114,12 +114,12 @@ public String clientId() { } @Override - public void registerOutPublish(PublishInPacket publish, PendingMessageHandler handler, int packetId) { + public void registerOutPublish(PublishMqttInMessage publish, PendingMessageHandler handler, int packetId) { registerPublish(publish, handler, packetId, pendingOutPublishes); } @Override - public void registerInPublish(PublishInPacket publish, PendingMessageHandler handler, int packetId) { + public void registerInPublish(PublishMqttInMessage publish, PendingMessageHandler handler, int packetId) { registerPublish(publish, handler, packetId, pendingInPublishes); } @@ -174,12 +174,12 @@ public void resendPendingPackets(MqttClient mqttClient) { } @Override - public void updateOutPendingPacket(MqttClient client, HasPacketId response) { + public void updateOutPendingPacket(MqttClient client, HasMessageId response) { updatePendingPacket(client, response, pendingOutPublishes, clientId); } @Override - public void updateInPendingPacket(MqttClient client, HasPacketId response) { + public void updateInPendingPacket(MqttClient client, HasMessageId response) { updatePendingPacket(client, response, pendingInPublishes, clientId); } diff --git a/service/src/main/java/javasabr/mqtt/service/impl/InMemorySessionService.java b/service/src/main/java/javasabr/mqtt/service/session/impl/InMemoryMqttSessionService.java similarity index 91% rename from service/src/main/java/javasabr/mqtt/service/impl/InMemorySessionService.java rename to service/src/main/java/javasabr/mqtt/service/session/impl/InMemoryMqttSessionService.java index d6eaa8be..d2b81dc1 100644 --- a/service/src/main/java/javasabr/mqtt/service/impl/InMemorySessionService.java +++ b/service/src/main/java/javasabr/mqtt/service/session/impl/InMemoryMqttSessionService.java @@ -1,10 +1,9 @@ -package javasabr.mqtt.service.impl; +package javasabr.mqtt.service.session.impl; import java.io.Closeable; import javasabr.mqtt.network.MqttSession; import javasabr.mqtt.network.MqttSession.UnsafeMqttSession; -import javasabr.mqtt.network.impl.DefaultMqttSession; -import javasabr.mqtt.service.SessionService; +import javasabr.mqtt.service.session.MqttSessionService; import javasabr.rlib.collections.array.ArrayFactory; import javasabr.rlib.collections.array.MutableArray; import javasabr.rlib.collections.dictionary.Dictionary; @@ -19,7 +18,7 @@ @CustomLog @FieldDefaults(level = AccessLevel.PRIVATE) -public class InMemorySessionService implements SessionService, Closeable { +public class InMemoryMqttSessionService implements MqttSessionService, Closeable { final LockableRefToRefDictionary storedSession; final Thread cleanThread; @@ -27,7 +26,7 @@ public class InMemorySessionService implements SessionService, Closeable { final int cleanInterval; volatile boolean closed; - public InMemorySessionService(int cleanInterval) { + public InMemoryMqttSessionService(int cleanInterval) { this.cleanInterval = cleanInterval; this.storedSession = DictionaryFactory.stampedLockBasedRefToRefDictionary(); this.cleanThread = new Thread(this::cleanup, "InMemoryMqttSessionService-Cleanup"); @@ -66,7 +65,7 @@ public Mono create(String clientId) { log.debug(clientId, "Created new session for client:[%s]"::formatted); - return Mono.just(new DefaultMqttSession(clientId)); + return Mono.just(new InMemoryMqttSession(clientId)); } @Override @@ -106,7 +105,7 @@ private void cleanup() { storedSession .operations() - .inWriteLock(toRemove, InMemorySessionService::removeExpiredSessions); + .inWriteLock(toRemove, InMemoryMqttSessionService::removeExpiredSessions); } } diff --git a/service/src/main/java/javasabr/mqtt/service/session/impl/package-info.java b/service/src/main/java/javasabr/mqtt/service/session/impl/package-info.java new file mode 100644 index 00000000..332db8ca --- /dev/null +++ b/service/src/main/java/javasabr/mqtt/service/session/impl/package-info.java @@ -0,0 +1,4 @@ +@NullMarked +package javasabr.mqtt.service.session.impl; + +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/network/src/main/java/javasabr/mqtt/network/client/package-info.java b/service/src/main/java/javasabr/mqtt/service/session/package-info.java similarity index 58% rename from network/src/main/java/javasabr/mqtt/network/client/package-info.java rename to service/src/main/java/javasabr/mqtt/service/session/package-info.java index defb4d04..bbd3cff5 100644 --- a/network/src/main/java/javasabr/mqtt/network/client/package-info.java +++ b/service/src/main/java/javasabr/mqtt/service/session/package-info.java @@ -1,4 +1,4 @@ @NullMarked -package javasabr.mqtt.network.client; +package javasabr.mqtt.service.session; import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/test-support/build.gradle b/test-support/build.gradle index 25689237..af8324b7 100644 --- a/test-support/build.gradle +++ b/test-support/build.gradle @@ -1,5 +1,6 @@ plugins { - id "java-library" + id("java-library") + id("groovy") } dependencies { diff --git a/application/src/test/groovy/javasabr/mqtt/application/UnitSpecification.groovy b/test-support/src/main/groovy/javasabr/mqtt/test/support/UnitSpecification.groovy similarity index 70% rename from application/src/test/groovy/javasabr/mqtt/application/UnitSpecification.groovy rename to test-support/src/main/groovy/javasabr/mqtt/test/support/UnitSpecification.groovy index e7d5cba1..fa481c41 100644 --- a/application/src/test/groovy/javasabr/mqtt/application/UnitSpecification.groovy +++ b/test-support/src/main/groovy/javasabr/mqtt/test/support/UnitSpecification.groovy @@ -1,4 +1,4 @@ -package javasabr.mqtt.application +package javasabr.mqtt.test.support import spock.lang.Specification