Example usage for io.netty.buffer ByteBuf isReadable

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

Introduction

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

Prototype

public abstract boolean isReadable();

Source Link

Document

Returns true if and only if (this.writerIndex - this.readerIndex) is greater than 0 .

Usage

From source file:com.linecorp.armeria.client.endpoint.dns.DnsTextEndpointGroup.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.TXT) {
            continue;
        }/*from   ww w.j  a  v a  2s . co  m*/

        final ByteBuf content = ((ByteBufHolder) r).content();
        if (!content.isReadable()) { // Missing length octet
            warnInvalidRecord(DnsRecordType.TXT, content);
            continue;
        }

        content.markReaderIndex();
        final int txtLen = content.readUnsignedByte();
        if (txtLen == 0) { // Empty content
            continue;
        }

        if (content.readableBytes() != txtLen) { // Mismatching number of octets
            content.resetReaderIndex();
            warnInvalidRecord(DnsRecordType.TXT, content);
            continue;
        }

        final byte[] txt = new byte[txtLen];
        content.readBytes(txt);

        final Endpoint endpoint;
        try {
            endpoint = mapping.apply(txt);
        } catch (Exception e) {
            content.resetReaderIndex();
            warnInvalidRecord(DnsRecordType.TXT, content);
            continue;
        }

        if (endpoint != null) {
            if (endpoint.isGroup()) {
                logger().warn("{} Ignoring group endpoint: {}", logPrefix(), endpoint);
            } else {
                builder.add(endpoint);
            }
        }
    }

    final ImmutableSortedSet<Endpoint> endpoints = builder.build();
    if (logger().isDebugEnabled()) {
        logger().debug("{} Resolved: {} (TTL: {})", logPrefix(),
                endpoints.stream().map(Object::toString).collect(Collectors.joining(", ")), ttl);
    }

    return endpoints;
}

From source file:com.linecorp.armeria.client.thrift.ThriftClientCodec.java

License:Apache License

@SuppressWarnings({ "unchecked", "rawtypes" })
@Override//from   www .j av a  2 s .  c o  m
public <T> T decodeResponse(ServiceInvocationContext ctx, ByteBuf content, Object originalResponse)
        throws Exception {
    if (content == null) {
        return null;
    }

    if (!content.isReadable()) {
        ThriftMethod thriftMethod = getThriftMethod(ctx);
        if (thriftMethod != null && thriftMethod.isOneWay()) {
            return null;
        }
        throw new TApplicationException(TApplicationException.MISSING_RESULT, ctx.toString());
    }

    TByteBufInputTransport inputTransport = new TByteBufInputTransport(content);
    TProtocol inputProtocol = protocolFactory.getProtocol(inputTransport);
    TMessage msg = inputProtocol.readMessageBegin();
    if (msg.type == TMessageType.EXCEPTION) {
        TApplicationException ex = TApplicationException.read(inputProtocol);
        inputProtocol.readMessageEnd();
        throw ex;
    }
    ThriftMethod method = methodMap.get(msg.name);
    if (method == null) {
        throw new TApplicationException(TApplicationException.WRONG_METHOD_NAME, msg.name);
    }
    TBase<? extends TBase, TFieldIdEnum> result = method.createResult();
    result.read(inputProtocol);
    inputProtocol.readMessageEnd();

    for (TFieldIdEnum fieldIdEnum : method.getExceptionFields()) {
        if (result.isSet(fieldIdEnum)) {
            throw (TException) result.getFieldValue(fieldIdEnum);
        }
    }

    TFieldIdEnum successField = method.successField();
    if (successField == null) { //void method
        return null;
    }
    if (result.isSet(successField)) {
        return (T) result.getFieldValue(successField);
    }

    throw new TApplicationException(TApplicationException.MISSING_RESULT,
            result.getClass().getName() + '.' + successField.getFieldName());
}

From source file:com.linecorp.armeria.common.HttpData.java

License:Apache License

/**
 * Converts the specified Netty {@link ByteBuf} into an {@link HttpData}. Unlike {@link #of(byte[])}, this
 * method makes a copy of the {@link ByteBuf}.
 *
 * @return a new {@link HttpData}. {@link #EMPTY_DATA} if the readable bytes of {@code buf} is 0.
 *///from w  ww  .j a  v  a 2s .c  o m
static HttpData of(ByteBuf buf) {
    requireNonNull(buf, "buf");
    if (!buf.isReadable()) {
        return EMPTY_DATA;
    }
    return of(ByteBufUtil.getBytes(buf));
}

From source file:com.linecorp.armeria.server.http.tomcat.TomcatServiceInvocationHandler.java

License:Apache License

private Request convertRequest(ServiceInvocationContext ctx) {
    final FullHttpRequest req = ctx.originalRequest();
    final String mappedPath = ctx.mappedPath();

    final Request coyoteReq = new Request();

    // Set the remote host/address.
    final InetSocketAddress remoteAddr = (InetSocketAddress) ctx.remoteAddress();
    coyoteReq.remoteAddr().setString(remoteAddr.getAddress().getHostAddress());
    coyoteReq.remoteHost().setString(remoteAddr.getHostString());
    coyoteReq.setRemotePort(remoteAddr.getPort());

    // Set the local host/address.
    final InetSocketAddress localAddr = (InetSocketAddress) ctx.localAddress();
    coyoteReq.localAddr().setString(localAddr.getAddress().getHostAddress());
    coyoteReq.localName().setString(hostname());
    coyoteReq.setLocalPort(localAddr.getPort());

    // Set the method.
    final HttpMethod method = req.method();
    coyoteReq.method().setString(method.name());

    // Set the request URI.
    final byte[] uriBytes = mappedPath.getBytes(StandardCharsets.US_ASCII);
    coyoteReq.requestURI().setBytes(uriBytes, 0, uriBytes.length);

    // Set the query string if any.
    final int queryIndex = req.uri().indexOf('?');
    if (queryIndex >= 0) {
        coyoteReq.queryString().setString(req.uri().substring(queryIndex + 1));
    }//from  w  ww. j av a  2s.c o m

    // Set the headers.
    final MimeHeaders cHeaders = coyoteReq.getMimeHeaders();
    convertHeaders(req.headers(), cHeaders);
    convertHeaders(req.trailingHeaders(), cHeaders);

    // Set the content.
    final ByteBuf content = req.content();
    if (content.isReadable()) {
        coyoteReq.setInputBuffer(new InputBufferImpl(content));
    }

    return coyoteReq;
}

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   w  w w  . ja  va  2 s  . c  o  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.android.iotbroker.mqtt.parser.MQParser.java

License:Open Source License

private static LengthDetails decodeLength(ByteBuf buf) throws MalformedMessageException {
    int length = 0, multiplier = 1;
    int bytesUsed = 0;
    byte enc = 0;
    do {//from   w w  w  .  ja v a 2  s.  c om
        if (multiplier > 128 * 128 * 128)
            throw new MalformedMessageException("Encoded length exceeds maximum of 268435455 bytes");

        if (!buf.isReadable())
            return new LengthDetails(0, 0);

        enc = buf.readByte();
        length += (enc & 0x7f) * multiplier;
        multiplier *= 128;
        bytesUsed++;
    } while ((enc & 0x80) != 0);

    return new LengthDetails(length, bytesUsed);
}

From source file:com.mobius.software.mqtt.parser.avps.LengthDetails.java

License:Open Source License

public static LengthDetails decode(ByteBuf buf) throws MalformedMessageException {
    int length = 0, multiplier = 1;
    int bytesUsed = 0;
    byte enc = 0;
    do {// ww w.  j av a 2  s . c o  m
        if (multiplier > 128 * 128 * 128)
            throw new MalformedMessageException("Encoded length exceeds maximum of 268435455 bytes");

        if (!buf.isReadable())
            return new LengthDetails(0, 0);

        enc = buf.readByte();
        length += (enc & 0x7f) * multiplier;
        multiplier *= 128;
        bytesUsed++;
    } while ((enc & 0x80) != 0);

    return new LengthDetails(length, bytesUsed);
}

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 {/*from  w w w.ja va 2  s .  c o  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());
    }
}

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

License:Open Source License

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

    byte fixedHeader = buf.readByte();

    LengthDetails length = LengthDetails.decode(buf);

    MessageType type = MessageType.valueOf((fixedHeader >> 4) & 0xf);
    try {
        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:

            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);
            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<>();
            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<>();
            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<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");
            header = new Unsubscribe(unsubID, unsubscribeTopics.toArray(new Text[unsubscribeTopics.size()]));
            break;

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

        case PINGREQ:
            header = PINGREQ;
            break;
        case PINGRESP:
            header = PINGRESP;
            break;
        case DISCONNECT:
            header = 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());
    }
}

From source file:com.mpush.netty.codec.PacketDecoder.java

License:Apache License

private void decodeHeartbeat(ByteBuf in, List<Object> out) {
    while (in.isReadable()) {
        if (in.readByte() == Packet.HB_PACKET_BYTE) {
            out.add(Packet.HB_PACKET);/*from   ww  w .  j  a v a  2 s. co  m*/
        } else {
            in.readerIndex(in.readerIndex() - 1);
            break;
        }
    }
}