/* | |
* 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; | |
import com.google.common.base.MoreObjects.ToStringHelper; | |
/** | |
* 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 { | |
/* | |
<error>::=[<request-id-list> | <te-id-list>] | |
<error-obj-list> | |
<request-id-list>::=<RP>[<request-id-list>] | |
<te-id-list>::=<TE>[<te-id-list>] | |
*/ | |
protected static final Logger log = LoggerFactory.getLogger(PcepErrorVer1.class); | |
private boolean isErroInfoSet; | |
//PcepErrorObject list | |
private LinkedList<PcepErrorObject> llErrObjList; | |
//PcepRPObject list | |
private LinkedList<PcepRPObject> llRPObjList; | |
//PcepTEObject list | |
private LinkedList<PcepTEObject> 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<PcepRPObject> llRPObjList, LinkedList<PcepTEObject> llTEObjList, | |
LinkedList<PcepErrorObject> llErrObjListObjList) { | |
this.llRPObjList = llRPObjList; | |
this.llTEObjList = llTEObjList; | |
this.llErrObjList = llErrObjListObjList; | |
} | |
/** | |
* Constructor to initialize PcepError. | |
* | |
* @param llErrObjList list of PcepErrorObject | |
*/ | |
public PcepErrorVer1(LinkedList<PcepErrorObject> llErrObjList) { | |
this.llRPObjList = null; | |
this.llTEObjList = null; | |
this.llErrObjList = llErrObjList; | |
} | |
@Override | |
public LinkedList<PcepRPObject> getRPObjList() { | |
return this.llRPObjList; | |
} | |
@Override | |
public LinkedList<PcepTEObject> getTEObjList() { | |
return this.llTEObjList; | |
} | |
@Override | |
public LinkedList<PcepErrorObject> getErrorObjList() { | |
return this.llErrObjList; | |
} | |
/** | |
* Parse RP List from the channel buffer. | |
* | |
* @throws PcepParseException if mandatory fields are missing | |
* @param cb of type channel buffer | |
*/ | |
public void parseRPList(ChannelBuffer cb) throws PcepParseException { | |
byte yObjClass; | |
byte yObjType; | |
llRPObjList = new LinkedList<PcepRPObject>(); | |
// 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<PcepTEObject>(); | |
// 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<PcepErrorObject>(); | |
// 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<PcepRPObject> rpObjlistIterator = this.llRPObjList.listIterator(); | |
while (rpObjlistIterator.hasNext()) { | |
rpObjlistIterator.next().write(cb); | |
} | |
} | |
// TElist is optional | |
if (this.isTEObjListSet) { | |
ListIterator<PcepTEObject> teObjlistIterator = this.llTEObjList.listIterator(); | |
while (teObjlistIterator.hasNext()) { | |
teObjlistIterator.next().write(cb); | |
} | |
} | |
//ErrList is mandatory | |
ListIterator<PcepErrorObject> 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<PcepRPObject> llRPObjList; | |
private LinkedList<PcepTEObject> llTEObjList; | |
private LinkedList<PcepErrorObject> llErrObjList; | |
@Override | |
public PcepError build() { | |
return new PcepErrorVer1(llRPObjList, llTEObjList, llErrObjList); | |
} | |
@Override | |
public LinkedList<PcepRPObject> getRPObjList() { | |
return this.llRPObjList; | |
} | |
@Override | |
public Builder setRPObjList(LinkedList<PcepRPObject> llRPObjList) { | |
this.llRPObjList = llRPObjList; | |
return this; | |
} | |
@Override | |
public LinkedList<PcepTEObject> getTEObjList() { | |
return this.llTEObjList; | |
} | |
@Override | |
public Builder setTEObjList(LinkedList<PcepTEObject> llTEObjList) { | |
this.llTEObjList = llTEObjList; | |
return this; | |
} | |
@Override | |
public LinkedList<PcepErrorObject> getErrorObjList() { | |
return this.llErrObjList; | |
} | |
@Override | |
public Builder setErrorObjList(LinkedList<PcepErrorObject> llErrObjList) { | |
this.llErrObjList = llErrObjList; | |
return this; | |
} | |
} | |
@Override | |
public void setRPObjList(LinkedList<PcepRPObject> llRPObjList) { | |
this.llRPObjList = llRPObjList; | |
} | |
@Override | |
public void setTEObjList(LinkedList<PcepTEObject> llTEObjList) { | |
this.llTEObjList = llTEObjList; | |
} | |
@Override | |
public void setErrorObjList(LinkedList<PcepErrorObject> llErrObjList) { | |
this.llErrObjList = llErrObjList; | |
} | |
@Override | |
public String toString() { | |
ToStringHelper toStrHelper = MoreObjects.toStringHelper(getClass()); | |
//RP Object list is optional | |
if (null != llRPObjList) { | |
toStrHelper.add("RpObjectList", llRPObjList); | |
} | |
//TE Object list is optional | |
if (null != llTEObjList) { | |
toStrHelper.add("TeObjectList", llTEObjList); | |
} | |
//Error Object List is mandatory | |
return toStrHelper.add("ErrorObjectList", llErrObjList).toString(); | |
} | |
} |