/* * Copyright 2015 Open Networking Laboratory * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.onosproject.pcepio.protocol.ver1; import java.util.LinkedList; import java.util.ListIterator; import org.jboss.netty.buffer.ChannelBuffer; import org.onosproject.pcepio.exceptions.PcepParseException; import org.onosproject.pcepio.protocol.PcepError; import org.onosproject.pcepio.protocol.PcepErrorObject; import org.onosproject.pcepio.protocol.PcepRPObject; import org.onosproject.pcepio.protocol.PcepTEObject; import org.onosproject.pcepio.types.PcepObjectHeader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.MoreObjects; /** * Provides PcepError list which contains RP or TE objects. * Reference:PCEP Extension for Transporting TE Data draft-dhodylee-pce-pcep-te-data-extn-02. */ public class PcepErrorVer1 implements PcepError { /* ::=[ | ] ::=[] ::=[] */ protected static final Logger log = LoggerFactory.getLogger(PcepErrorVer1.class); private boolean isErroInfoSet; //PcepErrorObject list private LinkedList llErrObjList; //PcepRPObject list private LinkedList llRPObjList; //PcepTEObject list private LinkedList llTEObjList; private boolean isTEObjListSet; public static final int OBJECT_HEADER_LENGTH = 4; /** * Constructor to initialize variable. */ public PcepErrorVer1() { this.llRPObjList = null; this.llTEObjList = null; this.llErrObjList = null; } /** * Constructor to initialize variable. * * @param llRPObjList list of PcepRPObject * @param llTEObjList list of PcepTEObject * @param llErrObjListObjList list of PcepErrorObject */ public PcepErrorVer1(LinkedList llRPObjList, LinkedList llTEObjList, LinkedList llErrObjListObjList) { this.llRPObjList = llRPObjList; this.llTEObjList = llTEObjList; this.llErrObjList = llErrObjListObjList; } /** * Constructor to initialize PcepError. * * @param llErrObjList list of PcepErrorObject */ public PcepErrorVer1(LinkedList llErrObjList) { this.llRPObjList = null; this.llTEObjList = null; this.llErrObjList = llErrObjList; } @Override public LinkedList getRPObjList() { return this.llRPObjList; } @Override public LinkedList getTEObjList() { return this.llTEObjList; } @Override public LinkedList getErrorObjList() { return this.llErrObjList; } /** * Parse RP List from the channel buffer. * * @param cb of type channel buffer * @throws PcepParseException if mandatory fields are missing */ public void parseRPList(ChannelBuffer cb) throws PcepParseException { byte yObjClass; byte yObjType; llRPObjList = new LinkedList<>(); // caller should verify for RP object if (cb.readableBytes() < OBJECT_HEADER_LENGTH) { log.debug("Unable to find RP Object"); return; } cb.markReaderIndex(); PcepObjectHeader tempObjHeader = PcepObjectHeader.read(cb); cb.resetReaderIndex(); yObjClass = tempObjHeader.getObjClass(); yObjType = tempObjHeader.getObjType(); PcepRPObject rpObj; while ((yObjClass == PcepRPObjectVer1.RP_OBJ_CLASS) && (yObjType == PcepRPObjectVer1.RP_OBJ_TYPE)) { rpObj = PcepRPObjectVer1.read(cb); llRPObjList.add(rpObj); if (cb.readableBytes() > OBJECT_HEADER_LENGTH) { cb.markReaderIndex(); tempObjHeader = PcepObjectHeader.read(cb); cb.resetReaderIndex(); yObjClass = tempObjHeader.getObjClass(); yObjType = tempObjHeader.getObjType(); } else { break; } } } /** * Parse TE List from the channel buffer. * * @param cb of type channel buffer * @throws PcepParseException if mandatory fields are missing */ public void parseTEList(ChannelBuffer cb) throws PcepParseException { byte yObjClass; byte yObjType; llTEObjList = new LinkedList<>(); // caller should verify for TE object if (cb.readableBytes() < OBJECT_HEADER_LENGTH) { log.debug("Unable to find TE Object"); return; } cb.markReaderIndex(); PcepObjectHeader tempObjHeader = PcepObjectHeader.read(cb); cb.resetReaderIndex(); yObjClass = tempObjHeader.getObjClass(); yObjType = tempObjHeader.getObjType(); PcepTEObject teObj; while ((yObjClass == PcepTEObjectVer1.TE_OBJ_CLASS) && ((yObjType == PcepTEObjectVer1.TE_OBJ_TYPE_NODE_VALUE) || (yObjType == PcepTEObjectVer1.TE_OBJ_TYPE_LINK_VALUE))) { teObj = PcepTEObjectVer1.read(cb); llTEObjList.add(teObj); if (cb.readableBytes() > OBJECT_HEADER_LENGTH) { cb.markReaderIndex(); tempObjHeader = PcepObjectHeader.read(cb); cb.resetReaderIndex(); yObjClass = tempObjHeader.getObjClass(); yObjType = tempObjHeader.getObjType(); } else { break; } } } /** * parseErrObjList from the channel buffer. * * @param cb of type channel buffer * @throws PcepParseException if mandatory fields are missing */ public void parseErrObjList(ChannelBuffer cb) throws PcepParseException { byte yObjClass; byte yObjType; boolean bIsErrorObjFound = false; llErrObjList = new LinkedList<>(); // caller should verify for RP object if (cb.readableBytes() < OBJECT_HEADER_LENGTH) { throw new PcepParseException("Unable to find PCEP-ERROR Object"); } cb.markReaderIndex(); PcepObjectHeader tempObjHeader = PcepObjectHeader.read(cb); cb.resetReaderIndex(); yObjClass = tempObjHeader.getObjClass(); yObjType = tempObjHeader.getObjType(); PcepErrorObject errorObject; while ((yObjClass == PcepErrorObjectVer1.ERROR_OBJ_CLASS) && (yObjType == PcepErrorObjectVer1.ERROR_OBJ_TYPE)) { errorObject = PcepErrorObjectVer1.read(cb); llErrObjList.add(errorObject); bIsErrorObjFound = true; if (cb.readableBytes() > OBJECT_HEADER_LENGTH) { cb.markReaderIndex(); tempObjHeader = PcepObjectHeader.read(cb); cb.resetReaderIndex(); yObjClass = tempObjHeader.getObjClass(); yObjType = tempObjHeader.getObjType(); } else { break; } } if (!bIsErrorObjFound) { throw new PcepParseException("At least one PCEP-ERROR Object should be present."); } } /** * Reads the byte stream of PcepError from channel buffer. * * @param cb of type channel buffer * @return PcepError error part of PCEP-ERROR * @throws PcepParseException if mandatory fields are missing */ public static PcepErrorVer1 read(ChannelBuffer cb) throws PcepParseException { if (cb.readableBytes() < OBJECT_HEADER_LENGTH) { throw new PcepParseException("Unknown Object"); } PcepErrorVer1 pcepError = new PcepErrorVer1(); // check whether any PCEP Error Info is present cb.markReaderIndex(); PcepObjectHeader tempObjHeader = PcepObjectHeader.read(cb); cb.resetReaderIndex(); byte yObjClass = tempObjHeader.getObjClass(); //If RPlist present then store it.RPList and TEList are optional if (yObjClass == PcepRPObjectVer1.RP_OBJ_CLASS) { log.debug("RP_LIST"); pcepError.parseRPList(cb); yObjClass = checkNextObject(cb); } else if (yObjClass == PcepTEObjectVer1.TE_OBJ_CLASS) { log.debug("TE_LIST"); pcepError.parseTEList(cb); yObjClass = checkNextObject(cb); } if (yObjClass == PcepErrorObjectVer1.ERROR_OBJ_CLASS) { log.debug("PCEP-ERROR obj list"); pcepError.parseErrObjList(cb); yObjClass = checkNextObject(cb); } return pcepError; } /** * Checks Next Object. * * @param cb of type channel buffer. * @return object type class. */ private static byte checkNextObject(ChannelBuffer cb) { if (cb.readableBytes() < OBJECT_HEADER_LENGTH) { return 0; } cb.markReaderIndex(); PcepObjectHeader tempObjHeader = PcepObjectHeader.read(cb); cb.resetReaderIndex(); return tempObjHeader.getObjClass(); } /** * Writes the byte stream of PCEP error to the channel buffer. * * @param cb of type channel buffer * @return object length index * @throws PcepParseException if mandatory fields are missing */ @Override public int write(ChannelBuffer cb) throws PcepParseException { int iLenStartIndex = cb.writerIndex(); // RPlist is optional if (this.isErroInfoSet) { ListIterator rpObjlistIterator = this.llRPObjList.listIterator(); while (rpObjlistIterator.hasNext()) { rpObjlistIterator.next().write(cb); } } // TElist is optional if (this.isTEObjListSet) { ListIterator teObjlistIterator = this.llTEObjList.listIterator(); while (teObjlistIterator.hasNext()) { teObjlistIterator.next().write(cb); } } //ErrList is mandatory ListIterator errlistIterator = this.llErrObjList.listIterator(); while (errlistIterator.hasNext()) { errlistIterator.next().write(cb); } return cb.writerIndex() - iLenStartIndex; } /** * Builder for error part of PCEP-ERROR. */ public static class Builder implements PcepError.Builder { private LinkedList llRPObjList; private LinkedList llTEObjList; private LinkedList llErrObjList; @Override public PcepError build() { return new PcepErrorVer1(llRPObjList, llTEObjList, llErrObjList); } @Override public LinkedList getRPObjList() { return this.llRPObjList; } @Override public Builder setRPObjList(LinkedList llRPObjList) { this.llRPObjList = llRPObjList; return this; } @Override public LinkedList getTEObjList() { return this.llTEObjList; } @Override public Builder setTEObjList(LinkedList llTEObjList) { this.llTEObjList = llTEObjList; return this; } @Override public LinkedList getErrorObjList() { return this.llErrObjList; } @Override public Builder setErrorObjList(LinkedList llErrObjList) { this.llErrObjList = llErrObjList; return this; } } @Override public void setRPObjList(LinkedList llRPObjList) { this.llRPObjList = llRPObjList; } @Override public void setTEObjList(LinkedList llTEObjList) { this.llTEObjList = llTEObjList; } @Override public void setErrorObjList(LinkedList llErrObjList) { this.llErrObjList = llErrObjList; } @Override public String toString() { return MoreObjects.toStringHelper(getClass()) .omitNullValues() .add("RpObjectList", llRPObjList) .add("TeObjectList", llTEObjList) .add("ErrorObjectList", llErrObjList) .toString(); } }