Example usage for io.netty.buffer ByteBuf readShort

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

Introduction

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

Prototype

public abstract short readShort();

Source Link

Document

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

Usage

From source file:org.lanternpowered.server.network.pipeline.LegacyProtocolHandler.java

License:MIT License

@Override
public void channelRead(ChannelHandlerContext ctx, Object object) throws Exception {
    final LanternServer server = this.session.getServer();

    ByteBuf buf = (ByteBuf) object;
    buf.markReaderIndex();//w ww. ja v  a2 s  .  co  m

    // Whether it was a valid legacy message
    boolean legacy = false;

    try {
        final int messageId = buf.readUnsignedByte();
        // Old client's are not so smart, make sure that
        // they don't attempt to login
        if (messageId == 0x02) {
            int protocol = buf.readByte(); // Protocol version
            int value = buf.readShort();
            // Check the length
            if (value < 0 || value > 16) {
                return;
            }
            buf.readBytes(value << 1); // Username
            value = buf.readShort();
            // Check the length
            if (value < 0 || value > 255) {
                return;
            }
            buf.readBytes(value << 1); // Host address
            buf.readInt(); // Port
            if (buf.readableBytes() > 0) {
                return;
            }
            legacy = true;
            sendDisconnectMessage(ctx, LanternTexts.toPlain(t("multiplayer.disconnect.outdated_client",
                    Lantern.getGame().getPlatform().getMinecraftVersion().getName())));
            final MinecraftVersion clientVersion = Lantern.getGame().getMinecraftVersionCache()
                    .getVersionOrUnknown(protocol, true);
            if (clientVersion == LanternMinecraftVersion.UNKNOWN_LEGACY) {
                Lantern.getLogger().debug(
                        "Client with unknown legacy protocol version {} attempted to join the server.",
                        protocol);
            } else {
                Lantern.getLogger().debug(
                        "Client with legacy protocol version {} (mc-version {}) attempted to join the server.",
                        protocol, clientVersion.getName());
            }
            return;
        }

        // Check for the ping message id.
        if (messageId != 0xfe) {
            return;
        }

        int readable = buf.readableBytes();
        boolean full = false;

        // The version used to ping the server
        int protocol = V1_3_2_PROTOCOL;

        // Versions 1.4 - 1.5.x + 1.6 - Can request full data.
        if (readable > 0) {
            // Is always 1
            if (buf.readUnsignedByte() != 1) {
                return;
            }
            full = true;
            protocol = V1_5_2_PROTOCOL;
        }

        // The virtual address that was used to join the server
        InetSocketAddress virtualAddress = null;

        // Version 1.6 - Used extra data.
        if (readable > 1) {
            if (buf.readUnsignedByte() != 0xfa) {
                return;
            }
            byte[] bytes = new byte[buf.readShort() << 1];
            buf.readBytes(bytes);
            if (!new String(bytes, StandardCharsets.UTF_16BE).equals("MC|PingHost")) {
                return;
            }

            // Not used
            buf.readShort();

            // The protocol version is present
            protocol = buf.readUnsignedByte();

            // There is extra host and port data
            if (protocol >= 73) {
                bytes = new byte[buf.readShort() << 1];
                buf.readBytes(bytes);

                final String host = new String(bytes, StandardCharsets.UTF_16BE);
                final int port = buf.readInt();

                virtualAddress = InetSocketAddress.createUnresolved(host, port);
            }

            readable = buf.readableBytes();
            if (readable > 0) {
                Lantern.getLogger().warn("Trailing bytes on a legacy ping message: {}b", readable);
            }
        }

        final MinecraftVersion clientVersion = Lantern.getGame().getMinecraftVersionCache()
                .getVersionOrUnknown(protocol, true);
        if (clientVersion == LanternMinecraftVersion.UNKNOWN) {
            Lantern.getLogger().debug("Client with unknown legacy protocol version {} pinged the server.",
                    protocol);
        }

        // The message was successfully decoded as a legacy one
        legacy = true;

        final MinecraftVersion serverVersion = Lantern.getGame().getPlatform().getMinecraftVersion();
        Text description = server.getMotd();

        final InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress();
        final LanternStatusClient client = new LanternStatusClient(address, clientVersion, virtualAddress);
        final ClientPingServerEvent.Response.Players players = LanternStatusHelper.createPlayers(server);
        final LanternStatusResponse response = new LanternStatusResponse(serverVersion, server.getFavicon(),
                description, players);

        final ClientPingServerEvent event = SpongeEventFactory
                .createClientPingServerEvent(Cause.source(client).build(), client, response);
        Sponge.getEventManager().post(event);

        // Cancelled, we are done here
        if (event.isCancelled()) {
            ctx.channel().close();
            return;
        }

        description = response.getDescription();
        int online = players.getOnline();
        final int max = players.getMax();

        // The players should be hidden, this will replace the player count
        // with ???
        if (!response.getPlayers().isPresent()) {
            online = -1;
        }

        final String data;

        if (full) {
            final String description0 = getFirstLine(
                    TextSerializers.LEGACY_FORMATTING_CODE.serialize(description));
            // 1. This value is always 1.
            // 2. The protocol version, just use a value out of range
            //    of the available ones.
            // 3. The version/name string of the server.
            // 4. The motd of the server. In legacy format.
            // 5. The online players
            // 6. The maximum amount of players
            data = String.format("\u00A7%s\u0000%s\u0000%s\u0000%s\u0000%s\u0000%s", 1, 127,
                    response.getVersion().getName(), description0, online, max);
        } else {
            final String description0 = getFirstLine(TextSerializers.PLAIN.serialize(description));
            // 1. The motd of the server. In legacy format.
            // 2. The online players
            // 3. The maximum amount of players
            data = String.format("%s\u00A7%s\u00A7%s", description0, online, max);
        }

        sendDisconnectMessage(ctx, data);
    } catch (Exception ignore) {
    } finally {
        if (legacy) {
            buf.release();
        } else {
            buf.resetReaderIndex();
            ctx.channel().pipeline().remove(this);
            ctx.fireChannelRead(buf);
        }
    }
}

From source file:org.onosproject.lisp.msg.protocols.DefaultLispInfo.java

License:Apache License

public static LispInfo deserialize(ByteBuf byteBuf) throws LispParseError, LispReaderException {

    if (byteBuf.readerIndex() != 0) {
        return null;
    }/*  w  w w .j a v a 2s . c  om*/

    // infoReply -> 1 bit
    boolean infoReplyFlag = ByteOperator.getBit(byteBuf.readByte(), INFO_REPLY_INDEX);

    // let's skip the reserved field
    byteBuf.skipBytes(RESERVED_SKIP_LENGTH_1);

    // nonce -> 64 bits
    long nonce = byteBuf.readLong();

    // keyId -> 16 bits
    short keyId = byteBuf.readShort();

    // authenticationDataLength -> 16 bits
    short authLength = byteBuf.readShort();

    // authData -> depends on the authenticationDataLength
    byte[] authData = new byte[authLength];
    byteBuf.readBytes(authData);

    // ttl -> 32 bits
    int ttl = byteBuf.readInt();

    // let's skip the reserved field
    byteBuf.skipBytes(RESERVED_SKIP_LENGTH_2);

    // mask length -> 8 bits
    short maskLength = byteBuf.readUnsignedByte();

    LispAfiAddress prefix = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);

    return new DefaultLispInfo(infoReplyFlag, nonce, keyId, authLength, authData, ttl, (byte) maskLength,
            prefix);
}

From source file:org.opendaylight.capwap.ODLCapwapHeader.java

License:Open Source License

/**This method decodes the network bytes into capwap header format.
 * @param bbuf : ByteBuf of packets received from network
 * @return : true for success, false for failure
 *//*from  w  w  w  .  jav  a2 s  .c o m*/
public boolean decodeHeader(ByteBuf bbuf) {
    int pktlen = bbuf.readableBytes();

    if (pktlen < ODLCapwapConsts.ODL_CAPWAP_MIN_HDRLEN) {
        System.out.println("Invalid packet recieved. Length " + pktlen);
        return false;
    }

    preamble = bbuf.readByte();

    byte b;
    /* Header length - Most significant 5bits*4 */
    b = bbuf.readByte(); /* Read second byte */
    hlen = (byte) (((b >> 3) & 0x1F) << 2);
    if (hlen >= pktlen) {
        System.out.println("Invalid packet hlen " + hlen + " more than packet length " + pktlen);
        return false;
    }

    byte bnext;
    bnext = bbuf.readByte(); /* Read third byte */
    /* Lower order 3bits from byte2 and higher 2 bits from byte3 */
    rid = (byte) (((b & 0x07) << 2) | ((bnext >> 6) & 0x03));
    /* Lower order 5 bits from byte 3 */
    wbid = (byte) ((bnext & 0x3E) >> 1);

    b = bnext;
    bnext = bbuf.readByte(); /* Read 4th byte */
    /* Lower 1 bit from byte3 and higher 5bits from byte 4*/
    flagBits = (byte) (((b & 0x01) << 5) | ((bnext & 0xF8) >> 3));

    if (isSetTbit() && (wbid != ODLCapwapConsts.ODL_CAPWAP_WBID_80211)) {
        System.out.println("Invalid WBID " + wbid);
        return false;
    }

    this.resvFlags = 0;

    /* Retrieves bytes 5 & 6 */
    fragId = bbuf.readShort();

    /* Retrieves bytes 7 & 8 */
    int tmpOffset = bbuf.readShort();
    /*Higher order 13 bits */
    fragOffset = (short) (tmpOffset >> 3);

    /* TODO - Handle RADIO MAC address and WSI later */
    if (isSetMbit()) {
        /* TODO - Handle Radio MAC address */
    }

    if (isSetWbit()) {
        /* TODO : Handle WSI */
    }

    return true;
}

From source file:org.opendaylight.capwap.ODLCapwapMessageElement.java

License:Open Source License

public static ODLCapwapMessageElement decodeFromByteBuf(ByteBuf bbuf) {
    short type, length;
    ByteBuf value;//from   ww  w . ja  v a 2  s  .  c  o m

    type = bbuf.readShort();
    length = bbuf.readShort();
    value = bbuf.readBytes(length); // TODO - Add validations

    return new ODLCapwapMessageElement(type, length, value);
}

From source file:org.opendaylight.netide.openflowjava.protocol.impl.deserialization.factories.OF10PacketOutInputMessageFactory.java

License:Open Source License

@Override
public PacketOutInput deserialize(ByteBuf rawMessage) {
    PacketOutInputBuilder builder = new PacketOutInputBuilder();
    builder.setVersion((short) EncodeConstants.OF10_VERSION_ID);
    builder.setXid(rawMessage.readUnsignedInt());
    builder.setBufferId(rawMessage.readUnsignedInt());
    builder.setInPort(new PortNumber((long) rawMessage.readUnsignedShort()));
    int actions_len = rawMessage.readShort();
    CodeKeyMaker keyMaker = CodeKeyMakerFactory.createActionsKeyMaker(EncodeConstants.OF10_VERSION_ID);
    List<Action> actions = ListDeserializer.deserializeList(EncodeConstants.OF10_VERSION_ID, actions_len,
            rawMessage, keyMaker, registry);
    builder.setAction(actions);//from w  ww  . ja v  a  2s. c o  m

    byte[] data = rawMessage.readBytes(rawMessage.readableBytes()).array();

    if (data != null) {

        builder.setData(data);
    }
    return builder.build();
}

From source file:org.opendaylight.netide.openflowjava.protocol.impl.deserialization.factories.PacketOutInputMessageFactory.java

License:Open Source License

@Override
public PacketOutInput deserialize(ByteBuf rawMessage) {
    PacketOutInputBuilder builder = new PacketOutInputBuilder();
    builder.setVersion((short) EncodeConstants.OF13_VERSION_ID);
    builder.setXid(rawMessage.readUnsignedInt());
    builder.setBufferId(rawMessage.readUnsignedInt());
    builder.setInPort(new PortNumber(rawMessage.readUnsignedInt()));
    int actions_len = rawMessage.readShort();
    rawMessage.skipBytes(PADDING);/*w w  w.ja v a 2  s. co  m*/
    CodeKeyMaker keyMaker = CodeKeyMakerFactory.createActionsKeyMaker(EncodeConstants.OF13_VERSION_ID);
    List<Action> actions = ListDeserializer.deserializeList(EncodeConstants.OF13_VERSION_ID, actions_len,
            rawMessage, keyMaker, registry);
    builder.setAction(actions);
    byte[] data = rawMessage.readBytes(rawMessage.readableBytes()).array();
    if (data != null) {
        builder.setData(data);
    }
    return builder.build();
}

From source file:org.opendaylight.netide.openflowjava.protocol.impl.serialization.factories.ErrorMessageFactoryTest.java

License:Open Source License

@Test
public void testSerialize() {
    ErrorMessageFactory serializer = new ErrorMessageFactory();
    SerializerRegistry registry = new NetIdeSerializerRegistryImpl();
    registry.init();/*from w w  w . j  a  v a2 s .  c om*/
    ByteBuf serializedBuffer = UnpooledByteBufAllocator.DEFAULT.buffer();
    serializer.serialize(message, serializedBuffer);
    BufferHelper.checkHeaderV13(serializedBuffer, MESSAGE_TYPE, 28);
    Assert.assertEquals("Wrong Type", message.getType().intValue(), serializedBuffer.readShort());
    Assert.assertEquals("Wrong Code", message.getCode().intValue(), serializedBuffer.readShort());
    Assert.assertArrayEquals("Wrong data", message.getData(),
            serializedBuffer.readBytes(serializedBuffer.readableBytes()).array());
}

From source file:org.opendaylight.netide.openflowjava.protocol.impl.serialization.factories.FlowRemovedMessageFactoryTest.java

License:Open Source License

@Test
public void testSerialize() {
    FlowRemovedMessageFactory serializer = new FlowRemovedMessageFactory();
    SerializerRegistry registry = new NetIdeSerializerRegistryImpl();
    registry.init();/*  w ww. ja v  a  2  s .c  o  m*/
    serializer.injectSerializerRegistry(registry);
    ByteBuf serializedBuffer = UnpooledByteBufAllocator.DEFAULT.buffer();
    serializer.serialize(message, serializedBuffer);
    BufferHelper.checkHeaderV13(serializedBuffer, MESSAGE_TYPE, 72);
    Assert.assertEquals("Wrong cookie", message.getCookie().longValue(), serializedBuffer.readLong());
    Assert.assertEquals("Wrong priority", message.getPriority().intValue(), serializedBuffer.readShort());
    Assert.assertEquals("Wrong reason", message.getReason().getIntValue(), serializedBuffer.readByte());
    Assert.assertEquals("Wrong Table ID", message.getTableId().getValue().intValue(),
            serializedBuffer.readUnsignedByte());
    Assert.assertEquals("Wrong duration sec", message.getDurationSec().intValue(), serializedBuffer.readInt());
    Assert.assertEquals("Wrong duration nsec", message.getDurationNsec().intValue(),
            serializedBuffer.readInt());
    Assert.assertEquals("Wrong Idle timeout", message.getIdleTimeout().intValue(),
            serializedBuffer.readShort());
    Assert.assertEquals("Wrong Hard timeout", message.getIdleTimeout().intValue(),
            serializedBuffer.readShort());
    Assert.assertEquals("Wrong Packet count", message.getPacketCount().longValue(),
            serializedBuffer.readLong());
    Assert.assertEquals("Wrong Byte count", message.getByteCount().longValue(), serializedBuffer.readLong());
    Assert.assertEquals("Wrong match type", 1, serializedBuffer.readUnsignedShort());
    serializedBuffer.skipBytes(EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
    Assert.assertEquals("Wrong oxm class", 0x8000, serializedBuffer.readUnsignedShort());
    short fieldAndMask = serializedBuffer.readUnsignedByte();
    Assert.assertEquals("Wrong oxm hasMask", 0, fieldAndMask & 1);
    Assert.assertEquals("Wrong oxm field", 1, fieldAndMask >> 1);
    serializedBuffer.skipBytes(EncodeConstants.SIZE_OF_BYTE_IN_BYTES);
    Assert.assertEquals("Wrong oxm value", 42, serializedBuffer.readUnsignedInt());
    Assert.assertEquals("Wrong oxm class", 0x8000, serializedBuffer.readUnsignedShort());
    fieldAndMask = serializedBuffer.readUnsignedByte();
    Assert.assertEquals("Wrong oxm hasMask", 0, fieldAndMask & 1);
    Assert.assertEquals("Wrong oxm field", 9, fieldAndMask >> 1);
    serializedBuffer.skipBytes(EncodeConstants.SIZE_OF_BYTE_IN_BYTES);
    Assert.assertEquals("Wrong oxm value", 4, serializedBuffer.readUnsignedByte());
    serializedBuffer.skipBytes(7);
}

From source file:org.opendaylight.netide.openflowjava.protocol.impl.serialization.factories.GetConfigReplyMessageFactoryTest.java

License:Open Source License

@Test
public void testSerialize() {
    GetConfigReplyMessageFactory serializer = new GetConfigReplyMessageFactory();
    SerializerRegistry registry = new NetIdeSerializerRegistryImpl();
    registry.init();/*from  w w  w  .j  a va 2  s .c  o  m*/
    ByteBuf serializedBuffer = UnpooledByteBufAllocator.DEFAULT.buffer();
    serializer.serialize(message, serializedBuffer);
    BufferHelper.checkHeaderV13(serializedBuffer, MESSAGE_TYPE, 12);
    Assert.assertEquals("Wrong Type", message.getFlags().getIntValue(), serializedBuffer.readShort());
    Assert.assertEquals("Wrong Code", message.getMissSendLen().intValue(), serializedBuffer.readShort());
}

From source file:org.opendaylight.netide.openflowjava.protocol.impl.serialization.factories.MultipartReplyMessageFactoryTest.java

License:Open Source License

@Test
public void testMultipartRequestTableFeaturesMessageFactory() throws Exception {
    builder.setType(MultipartType.forValue(12));
    MultipartReplyTableFeaturesCaseBuilder caseBuilder = new MultipartReplyTableFeaturesCaseBuilder();
    MultipartReplyTableFeaturesBuilder featuresBuilder = new MultipartReplyTableFeaturesBuilder();
    List<TableFeatures> tableFeaturesList = new ArrayList<>();
    TableFeaturesBuilder tableFeaturesBuilder = new TableFeaturesBuilder();
    tableFeaturesBuilder.setTableId((short) 8);
    tableFeaturesBuilder.setName("AAAABBBBCCCCDDDDEEEEFFFFGGGG");
    tableFeaturesBuilder.setMetadataMatch(new byte[] { 0x00, 0x01, 0x02, 0x03, 0x01, 0x04, 0x08, 0x01 });
    tableFeaturesBuilder.setMetadataWrite(new byte[] { 0x00, 0x07, 0x01, 0x05, 0x01, 0x00, 0x03, 0x01 });
    tableFeaturesBuilder.setConfig(new TableConfig(true));
    tableFeaturesBuilder.setMaxEntries(65L);
    List<TableFeatureProperties> properties = new ArrayList<>();
    TableFeaturePropertiesBuilder propBuilder = new TableFeaturePropertiesBuilder();
    propBuilder.setType(TableFeaturesPropType.OFPTFPTNEXTTABLES);
    NextTableRelatedTableFeaturePropertyBuilder nextPropBuilder = new NextTableRelatedTableFeaturePropertyBuilder();
    List<NextTableIds> nextIds = new ArrayList<>();
    nextIds.add(new NextTableIdsBuilder().setTableId((short) 1).build());
    nextIds.add(new NextTableIdsBuilder().setTableId((short) 2).build());
    nextPropBuilder.setNextTableIds(nextIds);
    propBuilder.addAugmentation(NextTableRelatedTableFeatureProperty.class, nextPropBuilder.build());
    properties.add(propBuilder.build());
    propBuilder = new TableFeaturePropertiesBuilder();
    propBuilder.setType(TableFeaturesPropType.OFPTFPTNEXTTABLESMISS);
    nextPropBuilder = new NextTableRelatedTableFeaturePropertyBuilder();
    nextIds = new ArrayList<>();
    nextPropBuilder.setNextTableIds(nextIds);
    propBuilder.addAugmentation(NextTableRelatedTableFeatureProperty.class, nextPropBuilder.build());
    properties.add(propBuilder.build());
    propBuilder = new TableFeaturePropertiesBuilder();
    propBuilder.setType(TableFeaturesPropType.OFPTFPTINSTRUCTIONS);
    InstructionRelatedTableFeaturePropertyBuilder insPropBuilder = new InstructionRelatedTableFeaturePropertyBuilder();
    List<Instruction> insIds = new ArrayList<>();
    InstructionBuilder insBuilder = new InstructionBuilder();
    insBuilder.setInstructionChoice(new WriteActionsCaseBuilder().build());
    insIds.add(insBuilder.build());//from w  w w.  j a  va 2  s.  c  o m
    insBuilder = new InstructionBuilder();
    insBuilder.setInstructionChoice(new GotoTableCaseBuilder().build());
    insIds.add(insBuilder.build());
    insPropBuilder.setInstruction(insIds);
    propBuilder.addAugmentation(InstructionRelatedTableFeatureProperty.class, insPropBuilder.build());
    properties.add(propBuilder.build());
    propBuilder = new TableFeaturePropertiesBuilder();
    propBuilder.setType(TableFeaturesPropType.OFPTFPTINSTRUCTIONSMISS);
    insPropBuilder = new InstructionRelatedTableFeaturePropertyBuilder();
    insIds = new ArrayList<>();
    insBuilder = new InstructionBuilder();
    insBuilder.setInstructionChoice(new WriteMetadataCaseBuilder().build());
    insIds.add(insBuilder.build());
    insBuilder = new InstructionBuilder();
    insBuilder.setInstructionChoice(new ApplyActionsCaseBuilder().build());
    insIds.add(insBuilder.build());
    insBuilder = new InstructionBuilder();
    insBuilder.setInstructionChoice(new MeterCaseBuilder().build());
    insIds.add(insBuilder.build());
    insBuilder = new InstructionBuilder();
    insBuilder.setInstructionChoice(new ClearActionsCaseBuilder().build());
    insIds.add(insBuilder.build());
    insBuilder = new InstructionBuilder();
    insBuilder.setInstructionChoice(new GotoTableCaseBuilder().build());
    insIds.add(insBuilder.build());
    insPropBuilder.setInstruction(insIds);
    propBuilder.addAugmentation(InstructionRelatedTableFeatureProperty.class, insPropBuilder.build());
    properties.add(propBuilder.build());
    tableFeaturesBuilder.setTableFeatureProperties(properties);
    tableFeaturesList.add(tableFeaturesBuilder.build());
    tableFeaturesBuilder = new TableFeaturesBuilder();
    tableFeaturesBuilder.setTableId((short) 8);
    tableFeaturesBuilder.setName("AAAABBBBCCCCDDDDEEEEFFFFGGGG");
    byte[] metadataMatch = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x01, 0x04, 0x08, 0x01 };
    tableFeaturesBuilder.setMetadataMatch(metadataMatch);
    byte[] metadataWrite = new byte[] { 0x00, 0x07, 0x01, 0x05, 0x01, 0x00, 0x03, 0x01 };
    tableFeaturesBuilder.setMetadataWrite(metadataWrite);
    tableFeaturesBuilder.setConfig(new TableConfig(true));
    tableFeaturesBuilder.setMaxEntries(67L);
    properties = new ArrayList<>();
    propBuilder = new TableFeaturePropertiesBuilder();
    propBuilder.setType(TableFeaturesPropType.OFPTFPTWRITEACTIONS);
    ActionRelatedTableFeaturePropertyBuilder actBuilder = new ActionRelatedTableFeaturePropertyBuilder();
    List<Action> actions = new ArrayList<>();
    ActionBuilder actionBuilder = new ActionBuilder();
    actionBuilder.setActionChoice(new OutputActionCaseBuilder().build());
    actions.add(actionBuilder.build());
    actBuilder.setAction(actions);
    propBuilder.addAugmentation(ActionRelatedTableFeatureProperty.class, actBuilder.build());
    properties.add(propBuilder.build());
    propBuilder = new TableFeaturePropertiesBuilder();
    propBuilder.setType(TableFeaturesPropType.OFPTFPTWRITEACTIONSMISS);
    actBuilder = new ActionRelatedTableFeaturePropertyBuilder();
    actions = new ArrayList<>();
    actBuilder.setAction(actions);
    propBuilder.addAugmentation(ActionRelatedTableFeatureProperty.class, actBuilder.build());
    properties.add(propBuilder.build());
    propBuilder = new TableFeaturePropertiesBuilder();
    propBuilder.setType(TableFeaturesPropType.OFPTFPTAPPLYACTIONS);
    actBuilder = new ActionRelatedTableFeaturePropertyBuilder();
    actions = new ArrayList<>();
    actBuilder.setAction(actions);
    propBuilder.addAugmentation(ActionRelatedTableFeatureProperty.class, actBuilder.build());
    properties.add(propBuilder.build());
    propBuilder = new TableFeaturePropertiesBuilder();
    propBuilder.setType(TableFeaturesPropType.OFPTFPTAPPLYACTIONSMISS);
    actBuilder = new ActionRelatedTableFeaturePropertyBuilder();
    actions = new ArrayList<>();
    actBuilder.setAction(actions);
    propBuilder.addAugmentation(ActionRelatedTableFeatureProperty.class, actBuilder.build());
    properties.add(propBuilder.build());
    propBuilder = new TableFeaturePropertiesBuilder();
    propBuilder.setType(TableFeaturesPropType.OFPTFPTMATCH);
    OxmRelatedTableFeaturePropertyBuilder oxmBuilder = new OxmRelatedTableFeaturePropertyBuilder();
    List<MatchEntry> entries = new ArrayList<>();
    MatchEntryBuilder entriesBuilder = new MatchEntryBuilder();
    entriesBuilder.setOxmClass(OpenflowBasicClass.class);
    entriesBuilder.setOxmMatchField(InPhyPort.class);
    entriesBuilder.setHasMask(false);
    entries.add(entriesBuilder.build());
    entriesBuilder = new MatchEntryBuilder();
    entriesBuilder.setOxmClass(OpenflowBasicClass.class);
    entriesBuilder.setOxmMatchField(InPort.class);
    entriesBuilder.setHasMask(false);
    entries.add(entriesBuilder.build());
    oxmBuilder.setMatchEntry(entries);
    propBuilder.addAugmentation(OxmRelatedTableFeatureProperty.class, oxmBuilder.build());
    properties.add(propBuilder.build());
    propBuilder = new TableFeaturePropertiesBuilder();
    propBuilder.setType(TableFeaturesPropType.OFPTFPTWILDCARDS);
    oxmBuilder = new OxmRelatedTableFeaturePropertyBuilder();
    entries = new ArrayList<>();
    oxmBuilder.setMatchEntry(entries);
    propBuilder.addAugmentation(OxmRelatedTableFeatureProperty.class, oxmBuilder.build());
    properties.add(propBuilder.build());
    propBuilder = new TableFeaturePropertiesBuilder();
    propBuilder.setType(TableFeaturesPropType.OFPTFPTWRITESETFIELD);
    oxmBuilder = new OxmRelatedTableFeaturePropertyBuilder();
    entries = new ArrayList<>();
    oxmBuilder.setMatchEntry(entries);
    propBuilder.addAugmentation(OxmRelatedTableFeatureProperty.class, oxmBuilder.build());
    properties.add(propBuilder.build());
    propBuilder = new TableFeaturePropertiesBuilder();
    propBuilder.setType(TableFeaturesPropType.OFPTFPTWRITESETFIELDMISS);
    oxmBuilder = new OxmRelatedTableFeaturePropertyBuilder();
    entries = new ArrayList<>();
    oxmBuilder.setMatchEntry(entries);
    propBuilder.addAugmentation(OxmRelatedTableFeatureProperty.class, oxmBuilder.build());
    properties.add(propBuilder.build());
    propBuilder = new TableFeaturePropertiesBuilder();
    propBuilder.setType(TableFeaturesPropType.OFPTFPTAPPLYSETFIELD);
    oxmBuilder = new OxmRelatedTableFeaturePropertyBuilder();
    entries = new ArrayList<>();
    entriesBuilder = new MatchEntryBuilder();
    entriesBuilder.setOxmClass(OpenflowBasicClass.class);
    entriesBuilder.setOxmMatchField(IpProto.class);
    entriesBuilder.setHasMask(false);
    entries.add(entriesBuilder.build());
    entriesBuilder = new MatchEntryBuilder();
    entriesBuilder.setOxmClass(OpenflowBasicClass.class);
    entriesBuilder.setOxmMatchField(IpEcn.class);
    entriesBuilder.setHasMask(false);
    entries.add(entriesBuilder.build());
    oxmBuilder.setMatchEntry(entries);
    propBuilder.addAugmentation(OxmRelatedTableFeatureProperty.class, oxmBuilder.build());
    properties.add(propBuilder.build());
    propBuilder = new TableFeaturePropertiesBuilder();
    propBuilder.setType(TableFeaturesPropType.OFPTFPTAPPLYSETFIELDMISS);
    oxmBuilder = new OxmRelatedTableFeaturePropertyBuilder();
    entries = new ArrayList<>();
    oxmBuilder.setMatchEntry(entries);
    propBuilder.addAugmentation(OxmRelatedTableFeatureProperty.class, oxmBuilder.build());
    properties.add(propBuilder.build());
    tableFeaturesBuilder.setTableFeatureProperties(properties);
    tableFeaturesList.add(tableFeaturesBuilder.build());
    featuresBuilder.setTableFeatures(tableFeaturesList);
    caseBuilder.setMultipartReplyTableFeatures(featuresBuilder.build());
    builder.setMultipartReplyBody(caseBuilder.build());
    message = builder.build();
    ByteBuf serializedBuffer = UnpooledByteBufAllocator.DEFAULT.buffer();
    serializer.serialize(message, serializedBuffer);
    BufferHelper.checkHeaderV13(serializedBuffer, MESSAGE_TYPE, 520);
    Assert.assertEquals("Wrong type", MultipartType.OFPMPTABLEFEATURES.getIntValue(),
            serializedBuffer.readShort());
    Assert.assertEquals("Wrong flags", message.getFlags(),
            createMultipartRequestFlags(serializedBuffer.readShort()));
    serializedBuffer.skipBytes(PADDING);

    Assert.assertEquals("Wrong length", 232, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong registry-id", 8, serializedBuffer.readUnsignedByte());
    serializedBuffer.skipBytes(5);
    Assert.assertEquals("Wrong name", "AAAABBBBCCCCDDDDEEEEFFFFGGGG",
            ByteBufUtils.decodeNullTerminatedString(serializedBuffer, 32));
    byte[] metadataMatchOutput = new byte[metadataMatch.length];
    serializedBuffer.readBytes(metadataMatchOutput);
    Assert.assertArrayEquals("Wrong metadata-match",
            new byte[] { 0x00, 0x01, 0x02, 0x03, 0x01, 0x04, 0x08, 0x01 }, metadataMatchOutput);
    serializedBuffer.skipBytes(64 - metadataMatch.length);
    byte[] metadataWriteOutput = new byte[metadataWrite.length];
    serializedBuffer.readBytes(metadataWriteOutput);
    Assert.assertArrayEquals("Wrong metadata-write",
            new byte[] { 0x00, 0x07, 0x01, 0x05, 0x01, 0x00, 0x03, 0x01 }, metadataWriteOutput);
    serializedBuffer.skipBytes(64 - metadataWrite.length);
    Assert.assertEquals("Wrong config", 1, serializedBuffer.readUnsignedInt());
    Assert.assertEquals("Wrong max-entries", 65, serializedBuffer.readUnsignedInt());
    Assert.assertEquals("Wrong property type", 2, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong property length", 6, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong next-registry-id", 1, serializedBuffer.readUnsignedByte());
    Assert.assertEquals("Wrong next-registry-id", 2, serializedBuffer.readUnsignedByte());
    serializedBuffer.skipBytes(2);
    Assert.assertEquals("Wrong property type", 3, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong property length", 4, serializedBuffer.readUnsignedShort());
    serializedBuffer.skipBytes(4);
    Assert.assertEquals("Wrong property type", 0, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong property length", 12, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong instruction type", 3, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong instruction length", 4, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong instruction type", 1, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong instruction length", 4, serializedBuffer.readUnsignedShort());
    serializedBuffer.skipBytes(4);
    Assert.assertEquals("Wrong property type", 1, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong property length", 24, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong instruction type", 2, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong instruction length", 4, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong instruction type", 4, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong instruction length", 4, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong instruction type", 6, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong instruction length", 4, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong instruction type", 5, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong instruction length", 4, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong instruction type", 1, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong instruction length", 4, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong length", 272, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong registry-id", 8, serializedBuffer.readUnsignedByte());
    serializedBuffer.skipBytes(5);
    Assert.assertEquals("Wrong name", "AAAABBBBCCCCDDDDEEEEFFFFGGGG",
            ByteBufUtils.decodeNullTerminatedString(serializedBuffer, 32));
    metadataMatchOutput = new byte[metadataMatch.length];
    serializedBuffer.readBytes(metadataMatchOutput);
    serializedBuffer.skipBytes(64 - metadataMatch.length);
    Assert.assertArrayEquals("Wrong metadata-match",
            new byte[] { 0x00, 0x01, 0x02, 0x03, 0x01, 0x04, 0x08, 0x01 }, metadataMatchOutput);
    metadataWriteOutput = new byte[metadataWrite.length];
    serializedBuffer.readBytes(metadataWriteOutput);
    serializedBuffer.skipBytes(64 - metadataWrite.length);
    Assert.assertArrayEquals("Wrong metadata-write",
            new byte[] { 0x00, 0x07, 0x01, 0x05, 0x01, 0x00, 0x03, 0x01 }, metadataWriteOutput);
    Assert.assertEquals("Wrong config", 1, serializedBuffer.readUnsignedInt());
    Assert.assertEquals("Wrong max-entries", 67, serializedBuffer.readUnsignedInt());
    Assert.assertEquals("Wrong property type", 4, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong property length", 8, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong action type", 0, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong action length", 4, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong property type", 5, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong property length", 4, serializedBuffer.readUnsignedShort());
    serializedBuffer.skipBytes(4);
    Assert.assertEquals("Wrong property type", 6, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong property length", 4, serializedBuffer.readUnsignedShort());
    serializedBuffer.skipBytes(4);
    Assert.assertEquals("Wrong property type", 7, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong property length", 4, serializedBuffer.readUnsignedShort());
    serializedBuffer.skipBytes(4);
    Assert.assertEquals("Wrong property type", 8, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong property length", 12, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong match class", 0x8000, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong match field&mask", 2, serializedBuffer.readUnsignedByte());
    Assert.assertEquals("Wrong match length", 4, serializedBuffer.readUnsignedByte());
    Assert.assertEquals("Wrong match class", 0x8000, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong match field&mask", 0, serializedBuffer.readUnsignedByte());
    Assert.assertEquals("Wrong match length", 4, serializedBuffer.readUnsignedByte());
    serializedBuffer.skipBytes(4);
    Assert.assertEquals("Wrong property type", 10, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong property length", 4, serializedBuffer.readUnsignedShort());
    serializedBuffer.skipBytes(4);
    Assert.assertEquals("Wrong property type", 12, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong property length", 4, serializedBuffer.readUnsignedShort());
    serializedBuffer.skipBytes(4);
    Assert.assertEquals("Wrong property type", 13, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong property length", 4, serializedBuffer.readUnsignedShort());
    serializedBuffer.skipBytes(4);
    Assert.assertEquals("Wrong property type", 14, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong property length", 12, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong match class", 0x8000, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong match field&mask", 20, serializedBuffer.readUnsignedByte());
    Assert.assertEquals("Wrong match length", 1, serializedBuffer.readUnsignedByte());
    Assert.assertEquals("Wrong match class", 0x8000, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong match field&mask", 18, serializedBuffer.readUnsignedByte());
    Assert.assertEquals("Wrong match length", 1, serializedBuffer.readUnsignedByte());
    serializedBuffer.skipBytes(4);
    Assert.assertEquals("Wrong property type", 15, serializedBuffer.readUnsignedShort());
    Assert.assertEquals("Wrong property length", 4, serializedBuffer.readUnsignedShort());
    serializedBuffer.skipBytes(4);
    Assert.assertTrue("Unread data", serializedBuffer.readableBytes() == 0);
}