X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=pcep%2Fspi%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fprotocol%2Fpcep%2Fspi%2FAbstractMessageParser.java;h=28252d038c6f71b717d4501f2c3de6f1be2217f0;hb=2894d2f6aaf1ed73ff9253cbd2fe283a4a471aa0;hp=bd29b3f9b97374c5ed74f57e94307ec463feb308;hpb=abbf207b7b4ef607df33d8917f851a6e3ac41183;p=bgpcep.git diff --git a/pcep/spi/src/main/java/org/opendaylight/protocol/pcep/spi/AbstractMessageParser.java b/pcep/spi/src/main/java/org/opendaylight/protocol/pcep/spi/AbstractMessageParser.java index bd29b3f9b9..28252d038c 100644 --- a/pcep/spi/src/main/java/org/opendaylight/protocol/pcep/spi/AbstractMessageParser.java +++ b/pcep/spi/src/main/java/org/opendaylight/protocol/pcep/spi/AbstractMessageParser.java @@ -7,140 +7,148 @@ */ package org.opendaylight.protocol.pcep.spi; -import java.util.Arrays; -import java.util.BitSet; -import java.util.List; +import static java.util.Objects.requireNonNull; -import org.opendaylight.protocol.util.ByteArray; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.PcerrBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Object; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.ObjectHeader; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcep.error.object.ErrorObjectBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.PcerrMessageBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.pcerr.message.ErrorsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.pcerr.message.error.type.RequestCaseBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.pcerr.message.error.type.request._case.RequestBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.pcerr.message.error.type.request._case.request.RpsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.rp.object.Rp; - -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; import com.google.common.primitives.UnsignedBytes; +import io.netty.buffer.ByteBuf; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import org.eclipse.jdt.annotation.Nullable; +import org.opendaylight.protocol.util.BitArray; +import org.opendaylight.protocol.util.ByteArray; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.iana.rev130816.EnterpriseNumber; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev181109.PcerrBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.Message; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.Object; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.ObjectHeader; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcep.error.object.ErrorObjectBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcerr.message.PcerrMessageBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcerr.message.pcerr.message.ErrorsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcerr.message.pcerr.message.error.type.RequestCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcerr.message.pcerr.message.error.type.request._case.RequestBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcerr.message.pcerr.message.error.type.request._case.request.RpsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.rp.object.Rp; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.vendor.information.objects.VendorInformationObject; +import org.opendaylight.yangtools.yang.common.netty.ByteBufUtils; public abstract class AbstractMessageParser implements MessageParser, MessageSerializer { - - private static final int COMMON_OBJECT_HEADER_LENGTH = 4; - - private static final int OC_F_LENGTH = 1; - private static final int OT_FLAGS_MF_LENGTH = 1; - private static final int OBJ_LENGTH_F_LENGTH = 2; - - private static final int OT_SF_LENGTH = 4; - private static final int FLAGS_SF_LENGTH = 4; - /* - * offsets of fields inside of multi-field in bits - */ - private static final int OT_SF_OFFSET = 0; - private static final int FLAGS_SF_OFFSET = OT_SF_OFFSET + OT_SF_LENGTH; - /* - * flags offsets inside multi-filed - */ - private static final int P_FLAG_OFFSET = 6; - private static final int I_FLAG_OFFSET = 7; - - private final ObjectHandlerRegistry registry; - - protected AbstractMessageParser(final ObjectHandlerRegistry registry) { - this.registry = Preconditions.checkNotNull(registry); - } - - protected byte[] serializeObject(final Object object) { - if (object == null) { - throw new IllegalArgumentException("Null object passed."); - } - final ObjectSerializer serializer = this.registry.getObjectSerializer(object); - return serializer.serializeObject(object); - } - - private List parseObjects(final byte[] bytes) throws PCEPDeserializerException { - int offset = 0; - final List objs = Lists.newArrayList(); - while (bytes.length - offset > 0) { - if (bytes.length - offset < COMMON_OBJECT_HEADER_LENGTH) { - throw new PCEPDeserializerException("Too few bytes in passed array. Passed: " + (bytes.length - offset) + " Expected: >= " - + COMMON_OBJECT_HEADER_LENGTH + "."); - } - - final int objClass = UnsignedBytes.toInt(bytes[offset]); - - offset += OC_F_LENGTH; - - final int objType = UnsignedBytes.toInt(ByteArray.copyBitsRange(bytes[offset], OT_SF_OFFSET, OT_SF_LENGTH)); - - final byte[] flagsBytes = { ByteArray.copyBitsRange(bytes[offset], FLAGS_SF_OFFSET, FLAGS_SF_LENGTH) }; - - final BitSet flags = ByteArray.bytesToBitSet(flagsBytes); - - offset += OT_FLAGS_MF_LENGTH; - - final int objLength = ByteArray.bytesToInt(ByteArray.subByte(bytes, offset, OBJ_LENGTH_F_LENGTH)); - - if (bytes.length - offset < objLength - COMMON_OBJECT_HEADER_LENGTH) { - throw new PCEPDeserializerException("Too few bytes in passed array. Passed: " + (bytes.length - offset) + " Expected: >= " - + objLength + "."); - } - - offset += OBJ_LENGTH_F_LENGTH; - - // copy bytes for deeper parsing - final byte[] bytesToPass = ByteArray.subByte(bytes, offset, objLength - COMMON_OBJECT_HEADER_LENGTH); - - offset += objLength - COMMON_OBJECT_HEADER_LENGTH; - - final ObjectParser parser = Preconditions.checkNotNull(this.registry.getObjectParser(objClass, objType)); - final ObjectHeader header = new ObjectHeaderImpl(flags.get(P_FLAG_OFFSET), flags.get(I_FLAG_OFFSET)); - - // parseObject is required to return null for P=0 errored objects - final Object o = parser.parseObject(header, bytesToPass); - if (o != null) { - objs.add(o); - } - } - - return objs; - } - - public static Message createErrorMsg(final PCEPErrors e) { - final PCEPErrorMapping maping = PCEPErrorMapping.getInstance(); - return new PcerrBuilder().setPcerrMessage( - new PcerrMessageBuilder().setErrors( - Arrays.asList(new ErrorsBuilder().setErrorObject( - new ErrorObjectBuilder().setType(maping.getFromErrorsEnum(e).type).setValue( - maping.getFromErrorsEnum(e).value).build()).build())).build()).build(); - } - - public static Message createErrorMsg(final PCEPErrors e, final Rp rp) { - final PCEPErrorMapping maping = PCEPErrorMapping.getInstance(); - return new PcerrBuilder().setPcerrMessage( - new PcerrMessageBuilder().setErrorType( - new RequestCaseBuilder().setRequest( - new RequestBuilder().setRps(Lists.newArrayList(new RpsBuilder().setRp(rp).build())).build()).build()).setErrors( - Arrays.asList(new ErrorsBuilder().setErrorObject( - new ErrorObjectBuilder().setType(maping.getFromErrorsEnum(e).type).setValue( - maping.getFromErrorsEnum(e).value).build()).build())).build()).build(); - } - - protected abstract Message validate(final List objects, final List errors) throws PCEPDeserializerException; - - @Override - public final Message parseMessage(final byte[] buffer, final List errors) throws PCEPDeserializerException { - Preconditions.checkNotNull(buffer, "Buffer may not be null"); - - // Parse objects first - final List objs = parseObjects(buffer); - - // Run validation - return validate(objs, errors); - } + private static final int COMMON_OBJECT_HEADER_LENGTH = 4; + private static final int OT_SF_LENGTH = 4; + + /* + * offsets of fields inside of multi-field in bits + */ + private static final int OT_SF_OFFSET = 0; + /* + * flags offsets inside multi-filed + */ + private static final int PROCESSED = 6; + private static final int IGNORED = 7; + + private final ObjectRegistry registry; + + protected AbstractMessageParser(final ObjectRegistry registry) { + this.registry = requireNonNull(registry); + } + + /** + * Calls registry to pick up specific object serializer for given object. + * Checks if the object is not null. + * @param object Object to be serialized, may be null + * @param buffer ByteBuf where the object should be serialized + */ + protected void serializeObject(final @Nullable Object object, final ByteBuf buffer) { + if (object != null) { + this.registry.serializeObject(object, buffer); + } + } + + private List parseObjects(final ByteBuf bytes) throws PCEPDeserializerException { + final List objs = new ArrayList<>(); + while (bytes.isReadable()) { + if (bytes.readableBytes() < COMMON_OBJECT_HEADER_LENGTH) { + throw new PCEPDeserializerException("Too few bytes in passed array. Passed: " + bytes.readableBytes() + + " Expected: >= " + COMMON_OBJECT_HEADER_LENGTH + "."); + } + final int objClass = bytes.readUnsignedByte(); + + final byte flagsByte = bytes.readByte(); + final BitArray flags = BitArray.valueOf(flagsByte); + final int objType = UnsignedBytes.toInt(ByteArray.copyBitsRange(flagsByte, OT_SF_OFFSET, OT_SF_LENGTH)); + final int objLength = bytes.readUnsignedShort(); + + if (bytes.readableBytes() < objLength - COMMON_OBJECT_HEADER_LENGTH) { + throw new PCEPDeserializerException("Too few bytes in passed array. Passed: " + bytes.readableBytes() + + " Expected: >= " + objLength + "."); + } + // copy bytes for deeper parsing + final ByteBuf bytesToPass = bytes.readSlice(objLength - COMMON_OBJECT_HEADER_LENGTH); + + final ObjectHeader header = new ObjectHeaderImpl(flags.get(PROCESSED), flags.get(IGNORED)); + + if (VendorInformationUtil.isVendorInformationObject(objClass, objType)) { + final EnterpriseNumber enterpriseNumber = new EnterpriseNumber(ByteBufUtils.readUint32(bytesToPass)); + final Optional obj = this.registry.parseVendorInformationObject(enterpriseNumber, + header, bytesToPass); + if (obj.isPresent()) { + objs.add(obj.get()); + } + } else { + // parseObject is required to return null for P=0 errored objects + final Object o = this.registry.parseObject(objClass, objType, header, bytesToPass); + if (o != null) { + objs.add(o); + } + } + } + + return objs; + } + + public static Message createErrorMsg(final PCEPErrors err, final Optional rp) { + final PcerrMessageBuilder msgBuilder = new PcerrMessageBuilder(); + if (rp.isPresent()) { + msgBuilder.setErrorType(new RequestCaseBuilder().setRequest(new RequestBuilder().setRps( + Collections.singletonList(new RpsBuilder().setRp(rp.get()).build())).build()).build()); + } + return new PcerrBuilder().setPcerrMessage( + msgBuilder.setErrors(Collections.singletonList(new ErrorsBuilder().setErrorObject( + new ErrorObjectBuilder().setType(err.getErrorType()).setValue( + err.getErrorValue()).build()).build())).build()).build(); + } + + protected abstract Message validate(List objects, List errors) throws PCEPDeserializerException; + + @Override + public final Message parseMessage(final ByteBuf buffer, final List errors) + throws PCEPDeserializerException { + requireNonNull(buffer, "Buffer may not be null"); + + // Parse objects first + final List objs = parseObjects(buffer); + + // Run validation + return validate(objs, errors); + } + + protected final void serializeVendorInformationObjects(final List viObjects, + final ByteBuf buffer) { + if (viObjects != null) { + for (final VendorInformationObject viObject : viObjects) { + this.registry.serializeVendorInformationObject(viObject, buffer); + } + } + } + + protected static List addVendorInformationObjects(final List objects) { + final List vendorInfo = new ArrayList<>(); + while (!objects.isEmpty() && objects.get(0) instanceof VendorInformationObject) { + final VendorInformationObject viObject = (VendorInformationObject) objects.get(0); + vendorInfo.add(viObject); + objects.remove(0); + } + return vendorInfo; + } }