Example usage for io.netty.handler.codec.mqtt MqttConnectReturnCode CONNECTION_REFUSED_UNACCEPTABLE_PROTOCOL_VERSION

List of usage examples for io.netty.handler.codec.mqtt MqttConnectReturnCode CONNECTION_REFUSED_UNACCEPTABLE_PROTOCOL_VERSION

Introduction

In this page you can find the example usage for io.netty.handler.codec.mqtt MqttConnectReturnCode CONNECTION_REFUSED_UNACCEPTABLE_PROTOCOL_VERSION.

Prototype

MqttConnectReturnCode CONNECTION_REFUSED_UNACCEPTABLE_PROTOCOL_VERSION

To view the source code for io.netty.handler.codec.mqtt MqttConnectReturnCode CONNECTION_REFUSED_UNACCEPTABLE_PROTOCOL_VERSION.

Click Source Link

Usage

From source file:com.caricah.iotracah.core.handlers.ConnectionHandler.java

License:Apache License

/**
 * * 3.1.4 Response//from w  w  w  .jav a2  s . c  om
 * <p>
 * Note that a Server MAY support multiple protocols (including earlier versions of this protocol)
 * on the same TCP port or other network endpoint. If the Server determines that the protocol is MQTT 3.1.1
 * then it validates the connection attempt as follows.
 * <p>
 * 1.     If the Server does not receive a CONNECT Packet within a reasonable amount of time after
 * the Network Connection is established, the Server SHOULD close the connection.
 * <p>
 * 2.     The Server MUST validate that the CONNECT Packet conforms to section 3.1 and close
 * the Network Connection without sending a CONNACK if it does not conform [MQTT-3.1.4-1].
 * <p>
 * 3.     The Server MAY check that the contents of the CONNECT Packet meet any further restrictions
 * and MAY perform authentication and authorization checks. If any of these checks fail,
 * it SHOULD send an appropriate CONNACK response with a non-zero return code as described
 * in section 3.2 and it MUST close the Network Connection.
 * <p>
 * If validation is successful the Server performs the following steps.
 * <p>
 * 1.     If the ClientId represents a Client already connected to the Server then
 * the Server MUST disconnect the existing Client [MQTT-3.1.4-2].
 * 2.     The Server MUST perform the processing of CleanSession that is described
 * in section 3.1.2.4 [MQTT-3.1.4-3].
 * 3.     The Server MUST acknowledge the CONNECT Packet with a CONNACK Packet
 * containing a zero return code [MQTT-3.1.4-4].
 * 4.     Start message delivery and keep alive monitoring.
 * <p>
 * Clients are allowed to send further Control Packets immediately after sending a CONNECT Packet;
 * Clients need not wait for a CONNACK Packet to arrive from the Server. If the Server rejects the CONNECT,
 * it MUST NOT process any data sent by the Client after the CONNECT Packet [MQTT-3.1.4-5].
 * <p>
 * Non normative comment
 * Clients typically wait for a CONNACK Packet,
 * However, if the Client exploits its freedom to send Control Packets before it receives a CONNACK,
 * it might simplify the Client implementation as it does not have to police the connected state.
 * The Client accepts that any data that it sends before it receives a CONNACK packet from the
 * Server will not be processed if the Server rejects the connection.
 *
 * @return
 * @throws RetriableException
 * @throws UnRetriableException
 */
@Override
public void handle(ConnectMessage connectMessage) throws RetriableException, UnRetriableException {

    log.debug(" handle : client initiating a new connection.");

    /**
     * 2.     The Server MUST validate that the CONNECT Packet conforms to section 3.1 and close
     *        the Network Connection without sending a CONNACK if it does not conform [MQTT-3.1.4-1].
     *
     *        3.1[ The Server MUST process a second CONNECT Packet sent from a Client as a protocol
     *        violation and disconnect the Client [MQTT-3.1.0-2].  See section 4.8 for information about handling errors.]
     *
     *
     */

    try {

        if (!MqttVersion.MQTT_3_1_1.protocolName().equals(connectMessage.getProtocolName())
                && !MqttVersion.MQTT_3_1.protocolName().equals(connectMessage.getProtocolName())) {

            /**
             * If the protocol name is incorrect the Server MAY disconnect the Client,
             * or it MAY continue processing the CONNECT packet in accordance with some other specification.
             * In the latter case, the Server MUST NOT continue to process the CONNECT packet in line with
             * this specification [MQTT-3.1.2-1].
             *
             */

            throw new UnknownProtocalException();

        }

        if (MqttVersion.MQTT_3_1_1.protocolLevel() != connectMessage.getProtocalLevel()
                && MqttVersion.MQTT_3_1.protocolLevel() != connectMessage.getProtocalLevel()) {

            /**
             * The 8 bit unsigned value that represents the revision level of the protocol used by the Client.
             * The value of the Protocol Level field for the version 3.1.1 of the protocol is 4 (0x04).
             * The Server MUST respond to the CONNECT Packet with a CONNACK return code 0x01 (unacceptable protocol level)
             * and then disconnect the Client if the Protocol Level is not supported by the Server [MQTT-3.1.2-2].
             */

            throw new MqttUnacceptableProtocolVersionException();
        } else {
            log.debug(" handle: the required protocal was selected.");
        }

        //TODO:      The Server MUST validate that the reserved flag in the CONNECT Control Packet is set to zero and disconnect the Client if it is not zero [MQTT-3.1.2-3].

        //We now proceed to openning a session on our core service interface.
        boolean cleanSession = connectMessage.isCleanSession();

        /**
         * The Server MUST allow ClientIds which are between 1 and 23 UTF-8 encoded bytes in length,
         * and that contain only the characters
         *           "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" [MQTT-3.1.3-5].
         *
         * The Server MAY allow ClientIds that contain more than 23 encoded bytes.
         * The Server MAY allow ClientIds that contain characters not included in the list given above.
         *
         *
         * A Server MAY allow a Client to supply a ClientId that has a length of zero bytes,
         * however if it does so the Server MUST treat this as a special case and assign a unique ClientId to that Client.
         * It MUST then process the CONNECT packet as if the Client had provided that unique ClientId [MQTT-3.1.3-6].
         *
         */
        String clientIdentifier = connectMessage.getClientId();

        /**
         * If the Client supplies a zero-byte ClientId, the Client MUST also set CleanSession to 1 [MQTT-3.1.3-7].
         *
         * If the Client supplies a zero-byte ClientId with CleanSession set to 0,
         * the Server MUST respond to the CONNECT Packet with a CONNACK return code 0x02 (Identifier rejected)
         * and then close the Network Connection [MQTT-3.1.3-8].
         */
        if ((null == clientIdentifier || clientIdentifier.isEmpty())) {

            if (!cleanSession) {

                throw new MqttIdentifierRejectedException();
            }
        } else {

            //Run a regular expression to check for invalid characters in our clientIdentifier.
            if (!pattern.matcher(clientIdentifier).matches()) {

                throw new MqttIdentifierRejectedException();

            }

        }

        log.debug(" handle: we are ready now to obtain the core session.");

        Observable<IOTClient> newClientObservable = openSubject(connectMessage.getCluster(),
                connectMessage.getNodeId(), connectMessage.getConnectionId(), clientIdentifier, cleanSession,
                connectMessage.getUserName(), connectMessage.getPassword(), connectMessage.getKeepAliveTime(),
                connectMessage.getSourceHost(), connectMessage.getProtocol());

        newClientObservable.subscribe(

                (iotSession) -> {

                    log.debug(" handle: obtained a client session : {}. ", iotSession);

                    /**
                     * 3.     The Server MAY check that the contents of the CONNECT Packet meet any further restrictions
                     *        and MAY perform authentication and authorization checks. If any of these checks fail,
                     *        it SHOULD send an appropriate CONNACK response with a non-zero return code as described
                     *      in section 3.2 and it MUST close the Network Connection.
                     *
                     */

                    //Respond to server with a connection successfull.
                    ConnectAcknowledgeMessage connectAcknowledgeMessage = ConnectAcknowledgeMessage.from(
                            connectMessage.isDup(), connectMessage.getQos(), connectMessage.isRetain(),
                            connectMessage.getKeepAliveTime(), MqttConnectReturnCode.CONNECTION_ACCEPTED);
                    connectAcknowledgeMessage = iotSession.copyTransmissionData(connectAcknowledgeMessage);
                    connectAcknowledgeMessage.setAuthKey(iotSession.getAuthKey());
                    pushToServer(connectAcknowledgeMessage);

                    if (connectMessage.isHasWill()) {

                        /**
                         * If the Will Flag is set to 1 this indicates that, if the Connect request is accepted,
                         * a Will Message MUST be stored on the Server and associated with the Network Connection.
                         * The Will Message MUST be published when the Network Connection is subsequently closed unless
                         * the Will Message has been deleted by the Server on receipt of a DISCONNECT Packet [MQTT-3.1.2-8].
                         */

                        PublishMessage publishMessage = PublishMessage.from(PublishMessage.ID_TO_SHOW_IS_WILL,
                                false, connectMessage.getWillQos(), false, connectMessage.getWillTopic(),
                                ByteBuffer.wrap(connectMessage.getWillMessage().getBytes()), false);
                        publishMessage.setClientId(iotSession.getSessionId());
                        publishMessage.setSessionId(iotSession.getSessionId());
                        publishMessage.setPartitionId(iotSession.getPartitionId());

                        // We have the appropriate id's to save the will.

                        getDatastore().saveWill(iotSession, publishMessage);
                        log.debug(" handle: message has will : {} ", publishMessage);

                    } else {
                        //We need to clear the existing will if any.
                        getDatastore().removeWill(iotSession);
                    }

                    //Perform a reset for our session.
                    getWorker().getSessionResetManager().process(iotSession);

                },

                (e) -> {

                    log.error(" onError : Problems ", e);

                    ConnectAcknowledgeMessage connectAcknowledgeMessage;

                    if (e instanceof AuthenticationException) {

                        connectAcknowledgeMessage = ConnectAcknowledgeMessage.from(connectMessage.isDup(),
                                connectMessage.getQos(), connectMessage.isRetain(),
                                connectMessage.getKeepAliveTime(),
                                MqttConnectReturnCode.CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD);

                    } else if (e instanceof AuthorizationException) {

                        connectAcknowledgeMessage = ConnectAcknowledgeMessage.from(connectMessage.isDup(),
                                connectMessage.getQos(), connectMessage.isRetain(),
                                connectMessage.getKeepAliveTime(),
                                MqttConnectReturnCode.CONNECTION_REFUSED_NOT_AUTHORIZED);

                    } else {
                        connectAcknowledgeMessage = ConnectAcknowledgeMessage.from(connectMessage.isDup(),
                                connectMessage.getQos(), connectMessage.isRetain(),
                                connectMessage.getKeepAliveTime(),
                                MqttConnectReturnCode.CONNECTION_REFUSED_SERVER_UNAVAILABLE);
                    }

                    connectAcknowledgeMessage.copyTransmissionData(connectMessage);
                    pushToServer(connectAcknowledgeMessage);

                }, () -> {

                });
    } catch (MqttUnacceptableProtocolVersionException | MqttIdentifierRejectedException
            | AuthenticationException | UnknownProtocalException e) {

        log.debug(" handle : Client connection issues ", e);

        //Respond to server with a connection unsuccessfull.
        ConnectAcknowledgeMessage connectAcknowledgeMessage;

        if (e instanceof MqttIdentifierRejectedException) {
            connectAcknowledgeMessage = ConnectAcknowledgeMessage.from(connectMessage.isDup(),
                    connectMessage.getQos(), connectMessage.isRetain(), connectMessage.getKeepAliveTime(),
                    MqttConnectReturnCode.CONNECTION_REFUSED_IDENTIFIER_REJECTED);

        } else if (e instanceof MqttUnacceptableProtocolVersionException) {

            connectAcknowledgeMessage = ConnectAcknowledgeMessage.from(connectMessage.isDup(),
                    connectMessage.getQos(), connectMessage.isRetain(), connectMessage.getKeepAliveTime(),
                    MqttConnectReturnCode.CONNECTION_REFUSED_UNACCEPTABLE_PROTOCOL_VERSION);

        } else if (e instanceof UnknownProtocalException) {

            connectAcknowledgeMessage = ConnectAcknowledgeMessage.from(connectMessage.isDup(),
                    connectMessage.getQos(), connectMessage.isRetain(), connectMessage.getKeepAliveTime(),
                    MqttConnectReturnCode.CONNECTION_REFUSED_UNACCEPTABLE_PROTOCOL_VERSION);

        } else {
            connectAcknowledgeMessage = ConnectAcknowledgeMessage.from(connectMessage.isDup(),
                    connectMessage.getQos(), connectMessage.isRetain(), connectMessage.getKeepAliveTime(),
                    MqttConnectReturnCode.CONNECTION_REFUSED_SERVER_UNAVAILABLE);
        }

        connectAcknowledgeMessage.copyTransmissionData(connectMessage);
        throw new ShutdownException(connectAcknowledgeMessage);

    } catch (Exception systemError) {

        ConnectAcknowledgeMessage connectAcknowledgeMessage = ConnectAcknowledgeMessage.from(
                connectMessage.isDup(), connectMessage.getQos(), connectMessage.isRetain(),
                connectMessage.getKeepAliveTime(), MqttConnectReturnCode.CONNECTION_REFUSED_SERVER_UNAVAILABLE);
        connectAcknowledgeMessage.copyTransmissionData(connectMessage);
        log.error(" handle : System experienced the error ", systemError);
        throw new ShutdownException(connectAcknowledgeMessage);

    }

}

From source file:io.crate.mqtt.protocol.MqttProcessor.java

public void handleConnect(Channel channel, MqttConnectMessage msg) {
    String clientId = msg.payload().clientIdentifier();
    LOGGER.debug("CONNECT for client <{}>", clientId);

    if (!(msg.variableHeader().version() == MqttVersion.MQTT_3_1.protocolLevel()
            || msg.variableHeader().version() == MqttVersion.MQTT_3_1_1.protocolLevel())) {
        sendErrorResponse(channel, MqttConnectReturnCode.CONNECTION_REFUSED_UNACCEPTABLE_PROTOCOL_VERSION)
                .addListener(f -> LOGGER.warn("CONNECT sent UNACCEPTABLE_PROTOCOL_VERSION"));
        return;//from   w  w  w  .  j ava  2  s  .c  o  m
    }

    // We require the clean session header to be true if client id is not provided
    // See MQTT-3.1.3-8 http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html
    if (clientId == null || clientId.length() == 0) {
        if (msg.variableHeader().isCleanSession() == false) {
            sendErrorResponse(channel, MqttConnectReturnCode.CONNECTION_REFUSED_IDENTIFIER_REJECTED)
                    .addListener(cf -> LOGGER.warn("CONNECT sent IDENTIFIER_REJECTED"));
            return;
        }
        clientId = UUID.randomUUID().toString();
        LOGGER.info("Client connected with server generated identifier: {}", clientId);
    }
    NettyUtils.clientID(channel, clientId);

    int keepAlive = msg.variableHeader().keepAliveTimeSeconds();
    if (keepAlive > 0) {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Client connected with keepAlive of {} s", keepAlive);
        }
        NettyUtils.keepAlive(channel, keepAlive);

        if (channel.pipeline().names().contains("idleStateHandler")) {
            channel.pipeline().remove("idleStateHandler");
        }

        // avoid terminating connections too early
        int allIdleTimeSeconds = Math.round(keepAlive * 1.5f);
        channel.pipeline().addFirst("idleStateHandler", new IdleStateHandler(0, 0, allIdleTimeSeconds));
    }

    channel.writeAndFlush(MqttMessageFactory.newConnAck(MqttConnectReturnCode.CONNECTION_ACCEPTED, true))
            .addListener(cf -> LOGGER.info("CONNECT sent CONNECTION_ACCEPTED"));
}

From source file:io.crate.mqtt.protocol.MqttProcessorTest.java

@Test
public void testConnectWithWrongMqttVersion() throws Exception {
    EmbeddedChannel ch = new EmbeddedChannel();

    MqttFixedHeader fixedHeader = new MqttFixedHeader(MqttMessageType.CONNECT, false, MqttQoS.AT_LEAST_ONCE,
            false, 0);/*  ww  w.j av a2s.c o  m*/
    MqttConnectVariableHeader variableHeader = new MqttConnectVariableHeader("connect", (byte) 1, false, false,
            false, (byte) 1, false, false, 60);
    MqttConnectPayload payload = new MqttConnectPayload("mqttClient", "someTopic", new byte[0], null, null);
    processor.handleConnect(ch, (MqttConnectMessage) io.netty.handler.codec.mqtt.MqttMessageFactory
            .newMessage(fixedHeader, variableHeader, payload));

    MqttConnAckMessage response = ch.readOutbound();
    assertThat(response.variableHeader().connectReturnCode(),
            is(MqttConnectReturnCode.CONNECTION_REFUSED_UNACCEPTABLE_PROTOCOL_VERSION));
    assertFalse(response.variableHeader().isSessionPresent());
}

From source file:io.vertx.mqtt.test.MqttConnectionTest.java

License:Apache License

@Test
public void refusedUnacceptableProtocolVersion(TestContext context) {

    this.expectedReturnCode = MqttConnectReturnCode.CONNECTION_REFUSED_UNACCEPTABLE_PROTOCOL_VERSION;

    try {/* w ww .j a  va 2s  .c om*/
        MemoryPersistence persistence = new MemoryPersistence();
        MqttConnectOptions options = new MqttConnectOptions();
        // trying the old 3.1
        options.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1);
        MqttClient client = new MqttClient(String.format("tcp://%s:%d", MQTT_SERVER_HOST, MQTT_SERVER_PORT),
                "12345", persistence);
        client.connect(options);
        context.assertTrue(false);
    } catch (MqttException e) {
        context.assertTrue(e.getReasonCode() == MqttException.REASON_CODE_INVALID_PROTOCOL_VERSION);
        e.printStackTrace();
    }
}

From source file:io.vertx.mqtt.test.MqttConnectionTest.java

License:Apache License

@Override
protected void endpointHandler(MqttEndpoint endpoint) {

    MqttConnectReturnCode returnCode = this.expectedReturnCode;

    switch (this.expectedReturnCode) {

    case CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD:

        returnCode = (endpoint.auth().userName().equals(MQTT_USERNAME)
                && endpoint.auth().password().equals(MQTT_PASSWORD)) ? MqttConnectReturnCode.CONNECTION_ACCEPTED
                        : MqttConnectReturnCode.CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD;
        break;/*from ww  w .  j av a 2  s . c  o m*/

    case CONNECTION_REFUSED_UNACCEPTABLE_PROTOCOL_VERSION:

        returnCode = endpoint.protocolVersion() == MqttConnectOptions.MQTT_VERSION_3_1_1
                ? MqttConnectReturnCode.CONNECTION_ACCEPTED
                : MqttConnectReturnCode.CONNECTION_REFUSED_UNACCEPTABLE_PROTOCOL_VERSION;
        break;
    }

    log.info("return code = " + returnCode);

    if (returnCode == MqttConnectReturnCode.CONNECTION_ACCEPTED) {
        endpoint.accept(false);
    } else {
        endpoint.reject(returnCode);
    }

    this.endpoint = endpoint;
}

From source file:io.vertx.mqtt.test.server.MqttServerConnectionTest.java

License:Apache License

@Test
public void refusedUnacceptableProtocolVersion(TestContext context) {

    this.expectedReturnCode = MqttConnectReturnCode.CONNECTION_REFUSED_UNACCEPTABLE_PROTOCOL_VERSION;

    try {/*from   w  ww . jav  a 2s  .c o  m*/
        MemoryPersistence persistence = new MemoryPersistence();
        MqttConnectOptions options = new MqttConnectOptions();
        // trying the old 3.1
        options.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1);
        MqttClient client = new MqttClient(String.format("tcp://%s:%d", MQTT_SERVER_HOST, MQTT_SERVER_PORT),
                "12345", persistence);
        client.connect(options);
        context.fail();
    } catch (MqttException e) {
        context.assertTrue(e.getReasonCode() == MqttException.REASON_CODE_INVALID_PROTOCOL_VERSION);
    }
}

From source file:io.vertx.mqtt.test.server.MqttServerConnectionTest.java

License:Apache License

@Override
protected void endpointHandler(MqttEndpoint endpoint) {

    MqttConnectReturnCode returnCode = this.expectedReturnCode;

    switch (this.expectedReturnCode) {

    case CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD:

        returnCode = (endpoint.auth().userName().equals(MQTT_USERNAME)
                && endpoint.auth().password().equals(MQTT_PASSWORD)) ? MqttConnectReturnCode.CONNECTION_ACCEPTED
                        : MqttConnectReturnCode.CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD;
        break;//from   w ww .j a  va  2 s  . co  m

    case CONNECTION_REFUSED_UNACCEPTABLE_PROTOCOL_VERSION:

        returnCode = endpoint.protocolVersion() == MqttConnectOptions.MQTT_VERSION_3_1_1
                ? MqttConnectReturnCode.CONNECTION_ACCEPTED
                : MqttConnectReturnCode.CONNECTION_REFUSED_UNACCEPTABLE_PROTOCOL_VERSION;
        break;
    }

    log.info("return code = " + returnCode);

    if (returnCode == MqttConnectReturnCode.CONNECTION_ACCEPTED) {
        log.info("client id = " + endpoint.clientIdentifier());
        endpoint.accept(false);
    } else {
        endpoint.reject(returnCode);
    }

    this.endpoint = endpoint;
}