Example usage for io.netty.buffer ByteBuf readUnsignedShort

List of usage examples for io.netty.buffer ByteBuf readUnsignedShort

Introduction

In this page you can find the example usage for io.netty.buffer ByteBuf readUnsignedShort.

Prototype

public abstract int readUnsignedShort();

Source Link

Document

Gets an unsigned 16-bit short integer at the current readerIndex and increases the readerIndex by 2 in this buffer.

Usage

From source file:com.github.jrialland.ajpclient.impl.handlers.AjpMessagesHandler.java

License:Apache License

protected Long readHeaders(final ChannelHandlerContext ctx, final ByteBuf in) throws Exception {
    final int statusCode = in.readUnsignedShort();
    final String statusMessage = readString(in);
    final int numHeaders = in.readUnsignedShort();

    if (getLog().isDebugEnabled()) {
        getLog().debug(" | HTTP/1.1 " + statusCode + " " + statusMessage);
    }/* www  . j a  v a2s.c o  m*/

    Long expected = null;
    final List<Header> headers = new ArrayList<Header>(numHeaders);

    for (int i = 0; i < numHeaders; i++) {
        in.markReaderIndex();
        final int code = in.readUnsignedShort();
        String headerName = ResponseHeader.getHeader(code);
        if (headerName == null) {
            in.resetReaderIndex();
            headerName = readString(in);
        }
        final String value = readString(in);
        if (getLog().isDebugEnabled()) {
            getLog().debug(" | " + headerName + ": " + value);
        }
        if (headerName.equalsIgnoreCase("Content-Length")) {
            expected = Long.parseLong(value);
        }
        headers.add(new Header(headerName, value));
    }
    getCallback(ctx.channel()).handleSendHeadersMessage(statusCode, statusMessage, headers);
    return expected;
}

From source file:com.github.jrialland.ajpclient.impl.handlers.AjpMessagesHandler.java

License:Apache License

protected String readString(final ByteBuf in) {
    in.markReaderIndex();/*w  ww  .j  av a  2  s . co m*/
    final int b0 = in.readUnsignedByte();
    if (b0 == 0xff) {
        return null;
    }
    in.resetReaderIndex();
    final int length = in.readUnsignedShort();
    final byte[] data = new byte[length];
    in.readBytes(data);

    // skip trailing \0
    in.readByte();

    return new String(data);
}

From source file:com.github.sylvek.wsmqttfwd.decoder.ConnectDecoder.java

License:Open Source License

@Override
public ConnectMessage decode(AttributeMap ctx, ByteBuf in) throws UnsupportedEncodingException {
    in.resetReaderIndex();//from w w w .jav  a 2  s  . c o m
    //Common decoding part
    ConnectMessage message = new ConnectMessage();
    if (!decodeCommonHeader(message, 0x00, in)) {
        in.resetReaderIndex();
        return null;
    }
    int remainingLength = message.getRemainingLength();
    int start = in.readerIndex();

    int protocolNameLen = in.readUnsignedShort();
    byte[] encProtoName;
    String protoName;
    Attribute<Integer> versionAttr = ctx.attr(PROTOCOL_VERSION);
    switch (protocolNameLen) {
    case 6:
        //MQTT version 3.1 "MQIsdp"
        //ProtocolName 8 bytes or 6 bytes
        if (in.readableBytes() < 10) {
            in.resetReaderIndex();
            return null;
        }

        encProtoName = new byte[6];
        in.readBytes(encProtoName);
        protoName = new String(encProtoName, "UTF-8");
        if (!"MQIsdp".equals(protoName)) {
            in.resetReaderIndex();
            throw new CorruptedFrameException("Invalid protoName: " + protoName);
        }
        message.setProtocolName(protoName);

        versionAttr.set((int) Utils.VERSION_3_1);
        break;
    case 4:
        //MQTT version 3.1.1 "MQTT"
        //ProtocolName 6 bytes
        if (in.readableBytes() < 8) {
            in.resetReaderIndex();
            return null;
        }
        encProtoName = new byte[4];
        in.readBytes(encProtoName);
        protoName = new String(encProtoName, "UTF-8");
        if (!"MQTT".equals(protoName)) {
            in.resetReaderIndex();
            throw new CorruptedFrameException("Invalid protoName: " + protoName);
        }
        message.setProtocolName(protoName);
        versionAttr.set((int) Utils.VERSION_3_1_1);
        break;
    default:
        //protocol broken
        throw new CorruptedFrameException("Invalid protoName size: " + protocolNameLen);
    }

    //ProtocolVersion 1 byte (value 0x03 for 3.1, 0x04 for 3.1.1)
    message.setProtocolVersion(in.readByte());
    if (message.getProtocolVersion() == Utils.VERSION_3_1_1) {
        //if 3.1.1, check the flags (dup, retain and qos == 0)
        if (message.isDupFlag() || message.isRetainFlag()
                || message.getQos() != AbstractMessage.QOSType.MOST_ONE) {
            throw new CorruptedFrameException("Received a CONNECT with fixed header flags != 0");
        }

        //check if this is another connect from the same client on the same session
        Attribute<Boolean> connectAttr = ctx.attr(ConnectDecoder.CONNECT_STATUS);
        Boolean alreadyConnected = connectAttr.get();
        if (alreadyConnected == null) {
            //never set
            connectAttr.set(true);
        } else if (alreadyConnected) {
            throw new CorruptedFrameException("Received a second CONNECT on the same network connection");
        }
    }

    //Connection flag
    byte connFlags = in.readByte();
    if (message.getProtocolVersion() == Utils.VERSION_3_1_1) {
        if ((connFlags & 0x01) != 0) { //bit(0) of connection flags is != 0
            throw new CorruptedFrameException("Received a CONNECT with connectionFlags[0(bit)] != 0");
        }
    }

    boolean cleanSession = ((connFlags & 0x02) >> 1) == 1;
    boolean willFlag = ((connFlags & 0x04) >> 2) == 1;
    byte willQos = (byte) ((connFlags & 0x18) >> 3);
    if (willQos > 2) {
        in.resetReaderIndex();
        throw new CorruptedFrameException("Expected will QoS in range 0..2 but found: " + willQos);
    }
    boolean willRetain = ((connFlags & 0x20) >> 5) == 1;
    boolean passwordFlag = ((connFlags & 0x40) >> 6) == 1;
    boolean userFlag = ((connFlags & 0x80) >> 7) == 1;
    //a password is true iff user is true.
    if (!userFlag && passwordFlag) {
        in.resetReaderIndex();
        throw new CorruptedFrameException(
                "Expected password flag to true if the user flag is true but was: " + passwordFlag);
    }
    message.setCleanSession(cleanSession);
    message.setWillFlag(willFlag);
    message.setWillQos(willQos);
    message.setWillRetain(willRetain);
    message.setPasswordFlag(passwordFlag);
    message.setUserFlag(userFlag);

    //Keep Alive timer 2 bytes
    //int keepAlive = Utils.readWord(in);
    int keepAlive = in.readUnsignedShort();
    message.setKeepAlive(keepAlive);

    if ((remainingLength == 12 && message.getProtocolVersion() == Utils.VERSION_3_1)
            || (remainingLength == 10 && message.getProtocolVersion() == Utils.VERSION_3_1_1)) {
        return message;
    }

    //Decode the ClientID
    String clientID = Utils.decodeString(in);
    if (clientID == null) {
        in.resetReaderIndex();
        return null;
    }
    message.setClientID(clientID);

    //Decode willTopic
    if (willFlag) {
        String willTopic = Utils.decodeString(in);
        if (willTopic == null) {
            in.resetReaderIndex();
            return null;
        }
        message.setWillTopic(willTopic);
    }

    //Decode willMessage
    if (willFlag) {
        byte[] willMessage = Utils.readFixedLengthContent(in);
        if (willMessage == null) {
            in.resetReaderIndex();
            return null;
        }
        message.setWillMessage(willMessage);
    }

    //Compatibility check with v3.0, remaining length has precedence over
    //the user and password flags
    int readed = in.readerIndex() - start;
    if (readed == remainingLength) {
        return message;
    }

    //Decode username
    if (userFlag) {
        String userName = Utils.decodeString(in);
        if (userName == null) {
            in.resetReaderIndex();
            return null;
        }
        message.setUsername(userName);
    }

    readed = in.readerIndex() - start;
    if (readed == remainingLength) {
        return message;
    }

    //Decode password
    if (passwordFlag) {
        byte[] password = Utils.readFixedLengthContent(in);
        if (password == null) {
            in.resetReaderIndex();
            return null;
        }
        message.setPassword(password);
    }

    return message;
}

From source file:com.github.sylvek.wsmqttfwd.decoder.PublishDecoder.java

License:Open Source License

@Override
public PublishMessage decode(AttributeMap ctx, ByteBuf in) throws Exception {
    LOG.debug("decode invoked with buffer {}", in);
    in.resetReaderIndex();/*  w  w  w. ja va2  s . co m*/
    int startPos = in.readerIndex();

    //Common decoding part
    PublishMessage message = new PublishMessage();
    if (!decodeCommonHeader(message, in)) {
        LOG.debug("decode ask for more data after {}", in);
        in.resetReaderIndex();
        return null;
    }

    int remainingLength = message.getRemainingLength();

    //Topic name
    String topic = Utils.decodeString(in);
    if (topic == null) {
        in.resetReaderIndex();
        return null;
    }
    //[MQTT-3.3.2-2] The Topic Name in the PUBLISH Packet MUST NOT contain wildcard characters.
    if (topic.contains("+") || topic.contains("#")) {
        throw new CorruptedFrameException(
                "Received a PUBLISH with topic containing wild card chars, topic: " + topic);
    }
    //check topic is at least one char [MQTT-4.7.3-1]
    if (topic.length() == 0) {
        throw new CorruptedFrameException("Received a PUBLISH with topic without any character");
    }

    message.setTopicName(topic);

    if (message.getQos() == AbstractMessage.QOSType.LEAST_ONE
            || message.getQos() == AbstractMessage.QOSType.EXACTLY_ONCE) {
        message.setMessageID(in.readUnsignedShort());
    }
    int stopPos = in.readerIndex();

    //read the payload
    int payloadSize = remainingLength - (stopPos - startPos - 2)
            + (Utils.numBytesToEncode(remainingLength) - 1);
    if (in.readableBytes() < payloadSize) {
        in.resetReaderIndex();
        return null;
    }
    ByteBuf bb = Unpooled.buffer(payloadSize);
    in.readBytes(bb);
    message.setPayload(bb.nioBuffer());

    return message;
}

From source file:com.github.sylvek.wsmqttfwd.decoder.SubscribeDecoder.java

License:Open Source License

@Override
public SubscribeMessage decode(AttributeMap ctx, ByteBuf in) throws Exception {
    //Common decoding part
    SubscribeMessage message = new SubscribeMessage();
    in.resetReaderIndex();/*from www . j  a va 2s.c o m*/
    if (!decodeCommonHeader(message, 0x02, in)) {
        in.resetReaderIndex();
        return null;
    }

    //check qos level
    if (message.getQos() != AbstractMessage.QOSType.LEAST_ONE) {
        throw new CorruptedFrameException(
                "Received SUBSCRIBE message with QoS other than LEAST_ONE, was: " + message.getQos());
    }

    int start = in.readerIndex();
    //read  messageIDs
    message.setMessageID(in.readUnsignedShort());
    int read = in.readerIndex() - start;
    while (read < message.getRemainingLength()) {
        decodeSubscription(in, message);
        read = in.readerIndex() - start;
    }

    if (message.subscriptions().isEmpty()) {
        throw new CorruptedFrameException("subscribe MUST have got at least 1 couple topic/QoS");
    }

    return message;
}

From source file:com.goodgamenow.source.serverquery.MasterQueryHandler.java

License:Open Source License

private static int decodePort(ByteBuf buf) {
    return buf.readUnsignedShort();
}

From source file:com.heliosapm.utils.buffer.BufferManager.java

License:Apache License

/**
 * Reads a UTF string from the passed ByteBuff
 * @param in The ByteBuf to read from/*from w  ww . j  a  v  a2 s.c o  m*/
 * @return the read string
 */
public final static String readUTF(final ByteBuf in) {
    try {
        int utflen = in.readUnsignedShort();
        byte[] bytearr = new byte[utflen];
        char[] chararr = new char[utflen];
        int c, char2, char3;
        int count = 0;
        int chararr_count = 0;
        in.readBytes(bytearr, 0, utflen);

        while (count < utflen) {
            c = bytearr[count] & 0xff;
            if (c > 127)
                break;
            count++;
            chararr[chararr_count++] = (char) c;
        }

        while (count < utflen) {
            c = bytearr[count] & 0xff;
            switch (c >> 4) {
            case 0:
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
            case 6:
            case 7:
                /* 0xxxxxxx*/
                count++;
                chararr[chararr_count++] = (char) c;
                break;
            case 12:
            case 13:
                /* 110x xxxx   10xx xxxx*/
                count += 2;
                if (count > utflen)
                    throw new UTFDataFormatException("malformed input: partial character at end");
                char2 = bytearr[count - 1];
                if ((char2 & 0xC0) != 0x80)
                    throw new UTFDataFormatException("malformed input around byte " + count);
                chararr[chararr_count++] = (char) (((c & 0x1F) << 6) | (char2 & 0x3F));
                break;
            case 14:
                /* 1110 xxxx  10xx xxxx  10xx xxxx */
                count += 3;
                if (count > utflen)
                    throw new UTFDataFormatException("malformed input: partial character at end");
                char2 = bytearr[count - 2];
                char3 = bytearr[count - 1];
                if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
                    throw new UTFDataFormatException("malformed input around byte " + (count - 1));
                chararr[chararr_count++] = (char) (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6)
                        | ((char3 & 0x3F) << 0));
                break;
            default:
                /* 10xx xxxx,  1111 xxxx */
                throw new UTFDataFormatException("malformed input around byte " + count);
            }
        }
        // The number of chars produced may be less than utflen
        return new String(chararr, 0, chararr_count);
    } catch (Exception ex) {
        throw new RuntimeException(ex);
    }
}

From source file:com.linecorp.armeria.client.endpoint.dns.DnsServiceEndpointGroup.java

License:Apache License

@Override
ImmutableSortedSet<Endpoint> onDnsRecords(List<DnsRecord> records, int ttl) throws Exception {
    final ImmutableSortedSet.Builder<Endpoint> builder = ImmutableSortedSet.naturalOrder();
    for (DnsRecord r : records) {
        if (!(r instanceof DnsRawRecord) || r.type() != DnsRecordType.SRV) {
            continue;
        }//from   w  w w  .j a va  2  s  .  c  om

        final ByteBuf content = ((ByteBufHolder) r).content();
        if (content.readableBytes() <= 6) { // Too few bytes
            warnInvalidRecord(DnsRecordType.SRV, content);
            continue;
        }

        content.markReaderIndex();
        content.skipBytes(2); // priority unused
        final int weight = content.readUnsignedShort();
        final int port = content.readUnsignedShort();

        final Endpoint endpoint;
        try {
            final String target = stripTrailingDot(DefaultDnsRecordDecoder.decodeName(content));
            endpoint = port > 0 ? Endpoint.of(target, port) : Endpoint.of(target);
        } catch (Exception e) {
            content.resetReaderIndex();
            warnInvalidRecord(DnsRecordType.SRV, content);
            continue;
        }

        builder.add(endpoint.withWeight(weight));
    }

    final ImmutableSortedSet<Endpoint> endpoints = builder.build();
    if (logger().isDebugEnabled()) {
        logger().debug("{} Resolved: {} (TTL: {})", logPrefix(),
                endpoints.stream().map(e -> e.authority() + '/' + e.weight()).collect(Collectors.joining(", ")),
                ttl);
    }

    return endpoints;
}

From source file:com.mobius.software.android.iotbroker.mqtt.parser.MQParser.java

License:Open Source License

public static MQMessage decode(ByteBuf buf) throws MalformedMessageException, UnsupportedEncodingException {
    MQMessage header = null;//from ww w  . j  a  v a 2s  .co m

    byte fixedHeader = buf.readByte();

    LengthDetails length = decodeLength(buf);

    MessageType type = MessageType.valueOf((fixedHeader >> 4) & 0xf);
    switch (type) {
    case CONNECT:

        byte[] nameValue = new byte[buf.readUnsignedShort()];
        buf.readBytes(nameValue, 0, nameValue.length);
        String name = new String(nameValue, "UTF-8");
        if (!name.equals("MQTT"))
            throw new MalformedMessageException("CONNECT, protocol-name set to " + name);

        int protocolLevel = buf.readUnsignedByte();

        byte contentFlags = buf.readByte();

        boolean userNameFlag = (((contentFlags >> 7) & 1) == 1) ? true : false;
        boolean userPassFlag = (((contentFlags >> 6) & 1) == 1) ? true : false;
        boolean willRetain = (((contentFlags >> 5) & 1) == 1) ? true : false;
        QoS willQos = QoS.valueOf(((contentFlags & 0x1f) >> 3) & 3);
        if (willQos == null)
            throw new MalformedMessageException("CONNECT, will QoS set to " + willQos);
        boolean willFlag = (((contentFlags >> 2) & 1) == 1) ? true : false;

        if (willQos.getValue() > 0 && !willFlag)
            throw new MalformedMessageException("CONNECT, will QoS set to " + willQos + ", willFlag not set");

        if (willRetain && !willFlag)
            throw new MalformedMessageException("CONNECT, will retain set, willFlag not set");

        boolean cleanSession = (((contentFlags >> 1) & 1) == 1) ? true : false;

        boolean reservedFlag = ((contentFlags & 1) == 1) ? true : false;
        if (reservedFlag)
            throw new MalformedMessageException("CONNECT, reserved flag set to true");

        int keepalive = buf.readUnsignedShort();

        byte[] clientIdValue = new byte[buf.readUnsignedShort()];
        buf.readBytes(clientIdValue, 0, clientIdValue.length);
        String clientID = new String(clientIdValue, "UTF-8");
        if (!StringVerifier.verify(clientID))
            throw new MalformedMessageException(
                    "ClientID contains restricted characters: U+0000, U+D000-U+DFFF");

        Text willTopic = null;
        byte[] willMessage = null;
        String username = null;
        String password = null;

        Will will = null;
        if (willFlag) {
            if (buf.readableBytes() < 2)
                throw new MalformedMessageException("Invalid encoding will/username/password");

            byte[] willTopicValue = new byte[buf.readUnsignedShort()];
            if (buf.readableBytes() < willTopicValue.length)
                throw new MalformedMessageException("Invalid encoding will/username/password");

            buf.readBytes(willTopicValue, 0, willTopicValue.length);

            String willTopicName = new String(willTopicValue, "UTF-8");
            if (!StringVerifier.verify(willTopicName))
                throw new MalformedMessageException(
                        "WillTopic contains one or more restricted characters: U+0000, U+D000-U+DFFF");
            willTopic = new Text(willTopicName);

            if (buf.readableBytes() < 2)
                throw new MalformedMessageException("Invalid encoding will/username/password");

            willMessage = new byte[buf.readUnsignedShort()];
            if (buf.readableBytes() < willMessage.length)
                throw new MalformedMessageException("Invalid encoding will/username/password");

            buf.readBytes(willMessage, 0, willMessage.length);
            if (willTopic.length() == 0)
                throw new MalformedMessageException("invalid will encoding");
            will = new Will(new Topic(willTopic, willQos), willMessage, willRetain);
            if (!will.isValid())
                throw new MalformedMessageException("invalid will encoding");
        }

        if (userNameFlag) {
            if (buf.readableBytes() < 2)
                throw new MalformedMessageException("Invalid encoding will/username/password");

            byte[] userNameValue = new byte[buf.readUnsignedShort()];
            if (buf.readableBytes() < userNameValue.length)
                throw new MalformedMessageException("Invalid encoding will/username/password");

            buf.readBytes(userNameValue, 0, userNameValue.length);
            username = new String(userNameValue, "UTF-8");
            if (!StringVerifier.verify(username))
                throw new MalformedMessageException(
                        "Username contains one or more restricted characters: U+0000, U+D000-U+DFFF");
        }

        if (userPassFlag) {
            if (buf.readableBytes() < 2)
                throw new MalformedMessageException("Invalid encoding will/username/password");

            byte[] userPassValue = new byte[buf.readUnsignedShort()];
            if (buf.readableBytes() < userPassValue.length)
                throw new MalformedMessageException("Invalid encoding will/username/password");

            buf.readBytes(userPassValue, 0, userPassValue.length);
            password = new String(userPassValue, "UTF-8");
            if (!StringVerifier.verify(password))
                throw new MalformedMessageException(
                        "Password contains one or more restricted characters: U+0000, U+D000-U+DFFF");
        }

        if (buf.readableBytes() > 0)
            throw new MalformedMessageException("Invalid encoding will/username/password");

        Connect connect = new Connect(username, password, clientID, cleanSession, keepalive, will);
        if (protocolLevel != 4)
            connect.setProtocolLevel(protocolLevel);
        header = connect;
        break;

    case CONNACK:
        byte sessionPresentValue = buf.readByte();
        if (sessionPresentValue != 0 && sessionPresentValue != 1)
            throw new MalformedMessageException(
                    String.format("CONNACK, session-present set to %d", sessionPresentValue & 0xff));
        boolean isPresent = sessionPresentValue == 1 ? true : false;

        short connackByte = buf.readUnsignedByte();
        ConnackCode connackCode = ConnackCode.valueOf(connackByte);
        if (connackCode == null)
            throw new MalformedMessageException("Invalid connack code: " + connackByte);
        header = new Connack(isPresent, connackCode);
        break;

    case PUBLISH:
        int dataLength = length.getLength();
        fixedHeader &= 0xf;

        boolean dup = (((fixedHeader >> 3) & 1) == 1) ? true : false;

        QoS qos = QoS.valueOf((fixedHeader & 0x07) >> 1);
        if (qos == null)
            throw new MalformedMessageException("invalid QoS value");
        if (dup && qos == QoS.AT_MOST_ONCE)
            throw new MalformedMessageException("PUBLISH, QoS-0 dup flag present");

        boolean retain = ((fixedHeader & 1) == 1) ? true : false;

        byte[] topicNameValue = new byte[buf.readUnsignedShort()];
        buf.readBytes(topicNameValue, 0, topicNameValue.length);
        String topicName = new String(topicNameValue, "UTF-8");
        if (!StringVerifier.verify(topicName))
            throw new MalformedMessageException(
                    "Publish-topic contains one or more restricted characters: U+0000, U+D000-U+DFFF");
        dataLength -= topicName.length() + 2;

        Integer packetID = null;
        if (qos != QoS.AT_MOST_ONCE) {
            packetID = buf.readUnsignedShort();
            if (packetID < 0 || packetID > 65535)
                throw new MalformedMessageException("Invalid PUBLISH packetID encoding");
            dataLength -= 2;
        }
        byte[] data = new byte[dataLength];
        if (dataLength > 0)
            buf.readBytes(data, 0, data.length);
        header = new Publish(packetID, new Topic(new Text(topicName), qos), data, retain, dup);
        break;

    case PUBACK:
        header = new Puback(buf.readUnsignedShort());
        break;

    case PUBREC:
        header = new Pubrec(buf.readUnsignedShort());
        break;

    case PUBREL:
        header = new Pubrel(buf.readUnsignedShort());
        break;

    case PUBCOMP:
        header = new Pubcomp(buf.readUnsignedShort());
        break;

    case SUBSCRIBE:
        Integer subID = buf.readUnsignedShort();
        List<Topic> subscriptions = new ArrayList<Topic>();
        while (buf.isReadable()) {
            byte[] value = new byte[buf.readUnsignedShort()];
            buf.readBytes(value, 0, value.length);
            QoS requestedQos = QoS.valueOf(buf.readByte());
            if (requestedQos == null)
                throw new MalformedMessageException(
                        "Subscribe qos must be in range from 0 to 2: " + requestedQos);
            String topic = new String(value, "UTF-8");
            if (!StringVerifier.verify(topic))
                throw new MalformedMessageException(
                        "Subscribe topic contains one or more restricted characters: U+0000, U+D000-U+DFFF");
            Topic subscription = new Topic(new Text(topic), requestedQos);
            subscriptions.add(subscription);
        }
        if (subscriptions.isEmpty())
            throw new MalformedMessageException("Subscribe with 0 topics");

        header = new Subscribe(subID, subscriptions.toArray(new Topic[subscriptions.size()]));
        break;

    case SUBACK:
        Integer subackID = buf.readUnsignedShort();
        List<SubackCode> subackCodes = new ArrayList<SubackCode>();
        while (buf.isReadable()) {
            short subackByte = buf.readUnsignedByte();
            SubackCode subackCode = SubackCode.valueOf(subackByte);
            if (subackCode == null)
                throw new MalformedMessageException("Invalid suback code: " + subackByte);
            subackCodes.add(subackCode);
        }
        if (subackCodes.isEmpty())
            throw new MalformedMessageException("Suback with 0 return-codes");

        header = new Suback(subackID, subackCodes);
        break;

    case UNSUBSCRIBE:
        Integer unsubID = buf.readUnsignedShort();
        List<Topic> unsubscribeTopics = new ArrayList<Topic>();
        while (buf.isReadable()) {
            byte[] value = new byte[buf.readUnsignedShort()];
            buf.readBytes(value, 0, value.length);
            String topic = new String(value, "UTF-8");
            if (!StringVerifier.verify(topic))
                throw new MalformedMessageException(
                        "Unsubscribe topic contains one or more restricted characters: U+0000, U+D000-U+DFFF");
            Topic subscription = new Topic(new Text(topic), QoS.AT_MOST_ONCE);
            unsubscribeTopics.add(subscription);
        }
        if (unsubscribeTopics.isEmpty())
            throw new MalformedMessageException("Unsubscribe with 0 topics");

        header = new Unsubscribe(unsubID, unsubscribeTopics.toArray(new Topic[unsubscribeTopics.size()]));
        break;

    case UNSUBACK:
        header = new Unsuback(buf.readUnsignedShort());
        break;

    case PINGREQ:
        header = new Pingreq();
        break;
    case PINGRESP:
        header = new Pingresp();
        break;
    case DISCONNECT:
        header = new Disconnect();
        break;

    default:
        throw new MalformedMessageException("Invalid header type: " + type);
    }

    if (buf.isReadable())
        throw new MalformedMessageException("unexpected bytes in content");

    if (length.getLength() != header.getLength())
        throw new MalformedMessageException(String.format("Invalid length. Encoded: %d, actual: %d",
                length.getLength(), header.getLength()));

    return header;
}

From source file:com.mobius.software.mqtt.parser.MQParser.java

License:Open Source License

public MQMessage decodeUsingCache(ByteBuf buf) throws MalformedMessageException {
    byte fixedHeader = buf.readByte();

    LengthDetails length = LengthDetails.decode(buf);

    MessageType type = MessageType.valueOf((fixedHeader >> 4) & 0xf);
    MQMessage header = cache.borrowMessage(type);
    try {// w  w  w .  j  a va2 s  .co  m
        switch (type) {
        case CONNECT:

            byte[] nameValue = new byte[buf.readUnsignedShort()];
            buf.readBytes(nameValue, 0, nameValue.length);
            String name = new String(nameValue, "UTF-8");
            if (!name.equals("MQTT"))
                throw new MalformedMessageException("CONNECT, protocol-name set to " + name);

            int protocolLevel = buf.readUnsignedByte();

            byte contentFlags = buf.readByte();

            boolean userNameFlag = ((contentFlags >> 7) & 1) == 1 ? true : false;
            boolean userPassFlag = ((contentFlags >> 6) & 1) == 1 ? true : false;
            boolean willRetain = ((contentFlags >> 5) & 1) == 1 ? true : false;
            QoS willQos = QoS.valueOf(((contentFlags & 0x1f) >> 3) & 3);
            if (willQos == null)
                throw new MalformedMessageException("CONNECT, will QoS set to " + willQos);
            boolean willFlag = (((contentFlags >> 2) & 1) == 1) ? true : false;

            if (willQos.getValue() > 0 && !willFlag)
                throw new MalformedMessageException(
                        "CONNECT, will QoS set to " + willQos + ", willFlag not set");

            if (willRetain && !willFlag)
                throw new MalformedMessageException("CONNECT, will retain set, willFlag not set");

            boolean cleanSession = ((contentFlags >> 1) & 1) == 1 ? true : false;

            boolean reservedFlag = (contentFlags & 1) == 1 ? true : false;
            if (reservedFlag)
                throw new MalformedMessageException("CONNECT, reserved flag set to true");

            int keepalive = buf.readUnsignedShort();

            byte[] clientIdValue = new byte[buf.readUnsignedShort()];
            buf.readBytes(clientIdValue, 0, clientIdValue.length);
            String clientID = new String(clientIdValue, "UTF-8");
            if (!StringVerifier.verify(clientID))
                throw new MalformedMessageException(
                        "ClientID contains restricted characters: U+0000, U+D000-U+DFFF");

            Text willTopic = null;
            byte[] willMessage = null;
            String username = null;
            String password = null;

            Will will = null;
            if (willFlag) {
                if (buf.readableBytes() < 2)
                    throw new MalformedMessageException("Invalid encoding will/username/password");

                byte[] willTopicValue = new byte[buf.readUnsignedShort()];
                if (buf.readableBytes() < willTopicValue.length)
                    throw new MalformedMessageException("Invalid encoding will/username/password");

                buf.readBytes(willTopicValue, 0, willTopicValue.length);

                String willTopicName = new String(willTopicValue, "UTF-8");
                if (!StringVerifier.verify(willTopicName))
                    throw new MalformedMessageException(
                            "WillTopic contains one or more restricted characters: U+0000, U+D000-U+DFFF");
                willTopic = new Text(willTopicName);

                if (buf.readableBytes() < 2)
                    throw new MalformedMessageException("Invalid encoding will/username/password");

                willMessage = new byte[buf.readUnsignedShort()];
                if (buf.readableBytes() < willMessage.length)
                    throw new MalformedMessageException("Invalid encoding will/username/password");

                buf.readBytes(willMessage, 0, willMessage.length);
                if (willTopic.length() == 0)
                    throw new MalformedMessageException("invalid will encoding");
                will = new Will(new Topic(willTopic, willQos), willMessage, willRetain);
                if (!will.isValid())
                    throw new MalformedMessageException("invalid will encoding");
            }

            if (userNameFlag) {
                if (buf.readableBytes() < 2)
                    throw new MalformedMessageException("Invalid encoding will/username/password");

                byte[] userNameValue = new byte[buf.readUnsignedShort()];
                if (buf.readableBytes() < userNameValue.length)
                    throw new MalformedMessageException("Invalid encoding will/username/password");

                buf.readBytes(userNameValue, 0, userNameValue.length);
                username = new String(userNameValue, "UTF-8");
                if (!StringVerifier.verify(username))
                    throw new MalformedMessageException(
                            "Username contains one or more restricted characters: U+0000, U+D000-U+DFFF");
            }

            if (userPassFlag) {
                if (buf.readableBytes() < 2)
                    throw new MalformedMessageException("Invalid encoding will/username/password");

                byte[] userPassValue = new byte[buf.readUnsignedShort()];
                if (buf.readableBytes() < userPassValue.length)
                    throw new MalformedMessageException("Invalid encoding will/username/password");

                buf.readBytes(userPassValue, 0, userPassValue.length);
                password = new String(userPassValue, "UTF-8");
                if (!StringVerifier.verify(password))
                    throw new MalformedMessageException(
                            "Password contains one or more restricted characters: U+0000, U+D000-U+DFFF");
            }

            if (buf.readableBytes() > 0)
                throw new MalformedMessageException("Invalid encoding will/username/password");

            Connect connect = (Connect) header;
            connect.reInit(username, password, clientID, cleanSession, keepalive, will);
            connect.setProtocolLevel(protocolLevel);
            break;

        case CONNACK:
            byte sessionPresentValue = buf.readByte();
            if (sessionPresentValue != 0 && sessionPresentValue != 1)
                throw new MalformedMessageException(
                        String.format("CONNACK, session-present set to %d", sessionPresentValue & 0xff));
            boolean isPresent = sessionPresentValue == 1 ? true : false;

            short connackByte = buf.readUnsignedByte();
            ConnackCode connackCode = ConnackCode.valueOf(connackByte);
            if (connackCode == null)
                throw new MalformedMessageException("Invalid connack code: " + connackByte);
            Connack connack = (Connack) header;
            connack.reInit(isPresent, connackCode);
            break;

        case PUBLISH:

            fixedHeader &= 0xf;

            boolean dup = ((fixedHeader >> 3) & 1) == 1 ? true : false;

            QoS qos = QoS.valueOf((fixedHeader & 0x07) >> 1);
            if (qos == null)
                throw new MalformedMessageException("invalid QoS value");
            if (dup && qos == QoS.AT_MOST_ONCE)
                throw new MalformedMessageException("PUBLISH, QoS-0 dup flag present");

            boolean retain = ((fixedHeader & 1) == 1) ? true : false;

            byte[] topicNameValue = new byte[buf.readUnsignedShort()];
            buf.readBytes(topicNameValue, 0, topicNameValue.length);
            String topicName = new String(topicNameValue, "UTF-8");
            if (!StringVerifier.verify(topicName))
                throw new MalformedMessageException(
                        "Publish-topic contains one or more restricted characters: U+0000, U+D000-U+DFFF");

            Integer packetID = null;
            if (qos != QoS.AT_MOST_ONCE) {
                packetID = buf.readUnsignedShort();
                if (packetID < 0 || packetID > 65535)
                    throw new MalformedMessageException("Invalid PUBLISH packetID encoding");
            }

            ByteBuf data = Unpooled.buffer(buf.readableBytes());
            data.writeBytes(buf);

            Publish publish = (Publish) header;
            publish.reInit(packetID, new Topic(new Text(topicName), qos), data, retain, dup);
            break;

        case PUBACK:
        case PUBREC:
        case PUBREL:
        case PUBCOMP:
        case UNSUBACK:
            CountableMessage countable = (CountableMessage) header;
            countable.reInit(buf.readUnsignedShort());
            break;

        case SUBSCRIBE:
            Integer subID = buf.readUnsignedShort();
            List<Topic> subscriptions = new ArrayList<>();
            while (buf.isReadable()) {
                byte[] value = new byte[buf.readUnsignedShort()];
                buf.readBytes(value, 0, value.length);
                QoS requestedQos = QoS.valueOf(buf.readByte());
                if (requestedQos == null)
                    throw new MalformedMessageException(
                            "Subscribe qos must be in range from 0 to 2: " + requestedQos);
                String topic = new String(value, "UTF-8");
                if (!StringVerifier.verify(topic))
                    throw new MalformedMessageException(
                            "Subscribe topic contains one or more restricted characters: U+0000, U+D000-U+DFFF");
                Topic subscription = new Topic(new Text(topic), requestedQos);
                subscriptions.add(subscription);
            }
            if (subscriptions.isEmpty())
                throw new MalformedMessageException("Subscribe with 0 topics");

            Subscribe subscribe = (Subscribe) header;
            subscribe.reInit(subID, subscriptions.toArray(new Topic[subscriptions.size()]));
            break;

        case SUBACK:
            Integer subackID = buf.readUnsignedShort();
            List<SubackCode> subackCodes = new ArrayList<>();
            while (buf.isReadable()) {
                short subackByte = buf.readUnsignedByte();
                SubackCode subackCode = SubackCode.valueOf(subackByte);
                if (subackCode == null)
                    throw new MalformedMessageException("Invalid suback code: " + subackByte);
                subackCodes.add(subackCode);
            }
            if (subackCodes.isEmpty())
                throw new MalformedMessageException("Suback with 0 return-codes");

            Suback suback = (Suback) header;
            suback.reInit(subackID, subackCodes);
            break;

        case UNSUBSCRIBE:
            Integer unsubID = buf.readUnsignedShort();
            List<Text> unsubscribeTopics = new ArrayList<>();
            while (buf.isReadable()) {
                byte[] value = new byte[buf.readUnsignedShort()];
                buf.readBytes(value, 0, value.length);
                String topic = new String(value, "UTF-8");
                if (!StringVerifier.verify(topic))
                    throw new MalformedMessageException(
                            "Unsubscribe topic contains one or more restricted characters: U+0000, U+D000-U+DFFF");
                unsubscribeTopics.add(new Text(topic));
            }
            if (unsubscribeTopics.isEmpty())
                throw new MalformedMessageException("Unsubscribe with 0 topics");
            Unsubscribe unsubscribe = (Unsubscribe) header;
            unsubscribe.reInit(unsubID, unsubscribeTopics.toArray(new Text[unsubscribeTopics.size()]));
            break;

        case PINGREQ:
        case PINGRESP:
        case DISCONNECT:
            break;

        default:
            throw new MalformedMessageException("Invalid header type: " + type);
        }

        if (buf.isReadable())
            throw new MalformedMessageException("unexpected bytes in content");

        if (length.getLength() != header.getLength())
            throw new MalformedMessageException(String.format("Invalid length. Encoded: %d, actual: %d",
                    length.getLength(), header.getLength()));

        return header;
    } catch (UnsupportedEncodingException e) {
        throw new MalformedMessageException("unsupported string encoding:" + e.getMessage());
    }
}