/* * Copyright 2015-present 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.List; 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.PcepLSObject; 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 LS objects. * Reference: draft-dhodylee-pce-pcep-ls-01, section 8.2. */ public class PcepErrorVer1 implements PcepError { /* <error>::=[<request-id-list> | <ls-id-list>] <error-obj-list> <request-id-list>::=<RP>[<request-id-list>] <ls-id-list>::=<LS>[<ls-id-list>] */ protected static final Logger log = LoggerFactory.getLogger(PcepErrorVer1.class); private boolean isErroInfoSet; //PcepErrorObject list private List<PcepErrorObject> errObjList; //PcepRPObject list private List<PcepRPObject> rpObjList; //PcepLSObject list private List<PcepLSObject> lsObjList; private boolean isLSObjListSet; public static final int OBJECT_HEADER_LENGTH = 4; /** * Constructor to initialize variable. */ public PcepErrorVer1() { this.rpObjList = null; this.lsObjList = null; this.errObjList = null; } /** * Constructor to initialize variable. * * @param rpObjList list of PcepRPObject * @param lsObjList list of PcepLSObject * @param errObjListObjList list of PcepErrorObject */ public PcepErrorVer1(List<PcepRPObject> rpObjList, List<PcepLSObject> lsObjList, List<PcepErrorObject> errObjListObjList) { this.rpObjList = rpObjList; this.lsObjList = lsObjList; this.errObjList = errObjListObjList; } /** * Constructor to initialize PcepError. * * @param errObjList list of PcepErrorObject */ public PcepErrorVer1(List<PcepErrorObject> errObjList) { this.rpObjList = null; this.lsObjList = null; this.errObjList = errObjList; } @Override public List<PcepRPObject> getRPObjList() { return this.rpObjList; } @Override public List<PcepLSObject> getLSObjList() { return this.lsObjList; } @Override public List<PcepErrorObject> getErrorObjList() { return this.errObjList; } /** * 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; rpObjList = 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); rpObjList.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 LS List from the channel buffer. * * @param cb of type channel buffer * @throws PcepParseException if mandatory fields are missing */ public void parseLSList(ChannelBuffer cb) throws PcepParseException { byte yObjClass; byte yObjType; lsObjList = new LinkedList<>(); // caller should verify for LS object if (cb.readableBytes() < OBJECT_HEADER_LENGTH) { log.debug("Unable to find LS Object"); return; } cb.markReaderIndex(); PcepObjectHeader tempObjHeader = PcepObjectHeader.read(cb); cb.resetReaderIndex(); yObjClass = tempObjHeader.getObjClass(); yObjType = tempObjHeader.getObjType(); PcepLSObject lsObj; while ((yObjClass == PcepLSObjectVer1.LS_OBJ_CLASS) && ((yObjType == PcepLSObjectVer1.LS_OBJ_TYPE_NODE_VALUE) || (yObjType == PcepLSObjectVer1.LS_OBJ_TYPE_LINK_VALUE))) { lsObj = PcepLSObjectVer1.read(cb); lsObjList.add(lsObj); 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; errObjList = 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); errObjList.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 LSList are optional if (yObjClass == PcepRPObjectVer1.RP_OBJ_CLASS) { log.debug("RP_LIST"); pcepError.parseRPList(cb); yObjClass = checkNextObject(cb); } else if (yObjClass == PcepLSObjectVer1.LS_OBJ_CLASS) { log.debug("LS_LIST"); pcepError.parseLSList(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<PcepRPObject> rpObjlistIterator = this.rpObjList.listIterator(); while (rpObjlistIterator.hasNext()) { rpObjlistIterator.next().write(cb); } } // LSlist is optional if (this.isLSObjListSet) { ListIterator<PcepLSObject> teObjlistIterator = this.lsObjList.listIterator(); while (teObjlistIterator.hasNext()) { teObjlistIterator.next().write(cb); } } //ErrList is mandatory ListIterator<PcepErrorObject> errlistIterator = this.errObjList.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 List<PcepRPObject> rpObjList; private List<PcepLSObject> lsObjList; private List<PcepErrorObject> errObjList; @Override public PcepError build() { return new PcepErrorVer1(rpObjList, lsObjList, errObjList); } @Override public List<PcepRPObject> getRPObjList() { return this.rpObjList; } @Override public Builder setRPObjList(List<PcepRPObject> rpObjList) { this.rpObjList = rpObjList; return this; } @Override public List<PcepLSObject> getLSObjList() { return this.lsObjList; } @Override public Builder setLSObjList(List<PcepLSObject> lsObjList) { this.lsObjList = lsObjList; return this; } @Override public List<PcepErrorObject> getErrorObjList() { return this.errObjList; } @Override public Builder setErrorObjList(List<PcepErrorObject> errObjList) { this.errObjList = errObjList; return this; } } @Override public void setRPObjList(List<PcepRPObject> rpObjList) { this.rpObjList = rpObjList; } @Override public void setLSObjList(List<PcepLSObject> lsObjList) { this.lsObjList = lsObjList; } @Override public void setErrorObjList(List<PcepErrorObject> errObjList) { this.errObjList = errObjList; } @Override public String toString() { return MoreObjects.toStringHelper(getClass()) .omitNullValues() .add("RpObjectList", rpObjList) .add("LsObjectList", lsObjList) .add("ErrorObjectList", errObjList) .toString(); } }